<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[juliu.is]]></title><description><![CDATA[A blog.]]></description><link>https://juliu.is</link><generator>GatsbyJS</generator><lastBuildDate>Mon, 20 Feb 2023 10:00:20 GMT</lastBuildDate><item><title><![CDATA[Tidying up your $HOME with Nix]]></title><description><![CDATA[I have four machines I often use: a 2022 M1 Macbook, my work laptop a 2017 Intel Macbook, my personal laptop a 2011 iMac, my… music player a…]]></description><link>https://juliu.is/tidying-your-home-with-nix/</link><guid isPermaLink="false">https://juliu.is/tidying-your-home-with-nix/</guid><pubDate>Fri, 17 Feb 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have four machines I often use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a 2022 M1 Macbook, my work laptop&lt;/li&gt;
&lt;li&gt;a 2017 Intel Macbook, my personal laptop&lt;/li&gt;
&lt;li&gt;a 2011 iMac, my… music player&lt;/li&gt;
&lt;li&gt;a Raspberry Pi 3, my &lt;a href=&quot;https://pi-hole.net/&quot;&gt;ad blocker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’d like to have the same development environment on all of these machines,
mostly for my bash, git, vim, and tmux configs. I’d also like to be able to
use all the nice little utilities I’m used to, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt; to fuzzy search &lt;em&gt;everything&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ogham/exa&quot;&gt;exa&lt;/a&gt; as a replacement for &lt;code class=&quot;language-text&quot;&gt;ls&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;ripgrep&lt;/a&gt; to search for stuff&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ajeetdsouza/zoxide&quot;&gt;zoxide&lt;/a&gt; as a smarter &lt;code class=&quot;language-text&quot;&gt;cd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/dandavison/delta&quot;&gt;delta&lt;/a&gt; for viewing diffs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As many of us do, I used to have a repo with a scrappy script that would
symlink all my configuration files and install a list of packages via
homebrew or apt.&lt;/p&gt;
&lt;p&gt;Except that it would often break. For example, I would install a vim plugin
that depends on Ruby: at install time, the plugin would be dynamically
linked against the existing version of Ruby. Whenever I updated Ruby, the vim
plugin would then start crashing. The fix? Reinstall the vim plugin so it
would be dynamically linked against the correct version of Ruby. I had to
do this every time I updated Ruby.
&lt;a href=&quot;https://github.com/wincent/command-t/issues/350&quot;&gt;Ugh&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Oh, remember my old iMac from 2011? Apparently, it’s so old that homebrew
stopped supporting it. Many times you won’t be able to find bottled
versions of programs and you’ll have to compile them from source, which
takes &lt;em&gt;ages&lt;/em&gt;. And sometimes the compilation crashes with random errors. It
seems I’m out of luck and I should give up, even though it’s a perfectly
functioning machine. Should I try to install Linux on it?&lt;/p&gt;
&lt;p&gt;It would be great if there was a way to provision a development environment
that worked on all of my machines, even the ones which are a bit obsolete.&lt;/p&gt;
&lt;h2 id=&quot;oh-but-there-is&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#oh-but-there-is&quot; aria-label=&quot;oh but there is permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Oh, but there is&lt;/h2&gt;
&lt;p&gt;I’ve already written about &lt;a href=&quot;/ditch-your-version-manager&quot;&gt;Nix&lt;/a&gt;, so feel
free to go and read that one first. Don’t feel like it? &lt;em&gt;Fine&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let’s install it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; https://nixos.org/nix/install&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This should work now:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nix-env &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
nix-env &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Nix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.13&lt;/span&gt;.2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I’m going to make you enable a feature called &lt;a href=&quot;https://www.tweag.io/blog/2020-05-25-flakes/&quot;&gt;Nix
flakes&lt;/a&gt;, which we’ll use to
lock the versions of our dependencies.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; ~/.config/nix

$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;EOF&lt;span class=&quot;token bash punctuation&quot;&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; ~/.config/nix/nix.conf&lt;/span&gt;
experimental-features = nix-command flakes
EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to get Nix to pick this up we need to restart the Nix daemon:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; launchctl kickstart &lt;span class=&quot;token parameter variable&quot;&gt;-k&lt;/span&gt; system/org.nixos.nix-daemon&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Great! Now we can create the folder to store all our configs:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-p&lt;/span&gt; ~/.config/nixpkgs &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/.config/nixpkgs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We are going to create a file called &lt;code class=&quot;language-text&quot;&gt;flake.nix&lt;/code&gt;, where we’ll define some
inputs and some outputs. The inputs are going to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/NixOS/nixpkgs&quot;&gt;nixpkgs&lt;/a&gt;, the repository of all nix packages&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nix-community/home-manager&quot;&gt;home-manager&lt;/a&gt;, the tool to manage your env&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What is going to be the output? Our dev environment :)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Home Manager configuration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  inputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nixos/nixpkgs/nixpkgs-unstable&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nix-community/home-manager&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      inputs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;follows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nixpkgs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  outputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    arch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;x86_64-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# or aarch64-darwin&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
      home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    homeConfigurations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;YOUR_USER &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# REPLACE ME&lt;/span&gt;&lt;/span&gt;      home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeManagerConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        modules &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./home.nix&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just be sure to choose the right architecture for your system,
&lt;code class=&quot;language-text&quot;&gt;x86_64-darwin&lt;/code&gt; for Intel Macs and &lt;code class=&quot;language-text&quot;&gt;aarch64-darwin&lt;/code&gt; for ARM Macs. Later I’m
going to explain how to support multiple architectures. Oh, and also make
sure to put your username instead of &lt;code class=&quot;language-text&quot;&gt;YOUR_USER&lt;/code&gt; 🙏&lt;/p&gt;
&lt;p&gt;You can see that we include a file called &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt;, which doesn’t
exist yet. Let’s create it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;YOUR_USER&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# REPLACE ME&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/YOUR_USER&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# REPLACE ME&lt;/span&gt;&lt;/span&gt;  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stateVersion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before we can try it out, flakes require all config files to be in a Git repository:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; init &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Perfect, now we’re ready to go:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;nix run &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt; switch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This command will install &lt;code class=&quot;language-text&quot;&gt;nixpkgs-unstable&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;home-manager&lt;/code&gt;, lock their versions in
a &lt;code class=&quot;language-text&quot;&gt;flake.lock&lt;/code&gt; file, and enable the first generation of our dev
environment. When it completes, we can check that it has been installed
correctly:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ home-manager &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;22.11&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hurray! 🎆&lt;/p&gt;
&lt;h2 id=&quot;adding-packages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#adding-packages&quot; aria-label=&quot;adding packages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Adding packages&lt;/h2&gt;
&lt;p&gt;Let’s modify our &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt; so that it looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stateVersion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;packages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sl&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we run &lt;code class=&quot;language-text&quot;&gt;home-manager switch&lt;/code&gt;, we’ll be greeted with an output like this
one:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ home-manager switch
Starting Home Manager activation
Activating checkFilesChanged
Activating checkLaunchAgents
Activating checkLinkTargets
Activating writeBoundary
Activating copyFonts
Activating installPackages
replacing old &lt;span class=&quot;token string&quot;&gt;&apos;home-manager-path&apos;&lt;/span&gt;
installing &lt;span class=&quot;token string&quot;&gt;&apos;home-manager-path&apos;&lt;/span&gt;
building &lt;span class=&quot;token string&quot;&gt;&apos;/nix/store/vj49hfv01fdgwd3igl9pi1kz4rlmj6x5-user-environment.drv&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.
Activating linkGeneration
Cleaning up orphan links from /Users/arkham
Creating profile generation &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
Creating home &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; links &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; /Users/arkham
Activating onFilesChange
Activating setupLaunchAgents&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ sl&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we’ll see something like this chugging along:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4c07efc881dff41517cc0fcbf551963d/71dc1/sl.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 53.16455696202532%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAtklEQVR42q2S2wrEIAxEtdqb1tIb/f8/zXKELCvYspQ+DEkMzowmxhgjL6PesNZ+o+aPCJumka7rZBxHads2g9p7L865AggRbwmnaZIY4ztPnuc5E5LjCOCYqC7/JuRpIQTp+16WZZFhGDI5dUpJ9n3PZyoEuFMRKQn1Mm63bZN1XXOOCD2c8m9KiGCVEHUIICMex5EjJOoY0AecnedZ+29TrIeq6yR18r9bAC4mfL2Hry/2U3wAiQXjFN1GmaEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;I like trains&quot;
        title=&quot;&quot;
        src=&quot;/static/4c07efc881dff41517cc0fcbf551963d/f058b/sl.png&quot;
        srcset=&quot;/static/4c07efc881dff41517cc0fcbf551963d/c26ae/sl.png 158w,
/static/4c07efc881dff41517cc0fcbf551963d/6bdcf/sl.png 315w,
/static/4c07efc881dff41517cc0fcbf551963d/f058b/sl.png 630w,
/static/4c07efc881dff41517cc0fcbf551963d/40601/sl.png 945w,
/static/4c07efc881dff41517cc0fcbf551963d/78612/sl.png 1260w,
/static/4c07efc881dff41517cc0fcbf551963d/71dc1/sl.png 2346w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;CHOO CHOO! 🚂 Notice that we downloaded a precompiled version of &lt;code class=&quot;language-text&quot;&gt;sl&lt;/code&gt;,
which is very similar to the bottled programs that homebrew provides. No
compilation needed! You can search
&lt;a href=&quot;https://search.nixos.org/packages?channel=unstable&quot;&gt;here&lt;/a&gt; for any package
you’d like to install.&lt;/p&gt;
&lt;p&gt;If you’re like me and love trains, you might already be satisfied. If you
want to see how &lt;code class=&quot;language-text&quot;&gt;home-manager&lt;/code&gt; manages both programs and configuration files,
keep on reading.&lt;/p&gt;
&lt;p&gt;Let’s go back inside &lt;code class=&quot;language-text&quot;&gt;~/.config/nixpkgs&lt;/code&gt; and copy our git config:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/.config/nixpkgs

$ &lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; ~/.gitconfig gitconfig&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And change &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt; to look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs, &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;. &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;: &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  home.username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home.homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home.stateVersion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  programs.home-manager.enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  home.packages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs.sl
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  programs.git &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token builtin class-name&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    includes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;~/.config/nixpkgs/gitconfig&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You’ll see that we specified that we want &lt;code class=&quot;language-text&quot;&gt;programs.git&lt;/code&gt; to be enabled. In
this way home-manager can install the program and manage its configuration
at the same time. As a rule of thumb, if it’s supported by home-manager
I’ll install the program using &lt;code class=&quot;language-text&quot;&gt;programs.&amp;lt;program&gt;&lt;/code&gt;. If not, I’ll add it to
&lt;code class=&quot;language-text&quot;&gt;home.packages&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we run &lt;code class=&quot;language-text&quot;&gt;home-manager switch -b bak&lt;/code&gt;, we’ll notice some things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the old config has been backed up as &lt;code class=&quot;language-text&quot;&gt;~/.gitconfig.bak&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;but now &lt;code class=&quot;language-text&quot;&gt;~/.gitconfig&lt;/code&gt; doesn’t exist anymore&lt;/li&gt;
&lt;li&gt;yet somehow, still, our git settings are working&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is because home-manager stores the git configuration inside
&lt;code class=&quot;language-text&quot;&gt;~/.config/git/config&lt;/code&gt;. If we look at that path we’ll be surprised:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-al&lt;/span&gt; ~/.config/git/config
lrwxr-xr-x &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; arkham staff &lt;span class=&quot;token number&quot;&gt;81&lt;/span&gt; Feb &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt; 00:01 /Users/arkham/.config
/git/config -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/mcnp2v50ndgxvkis1labl6784r8qwbj8-home
-manager-files/.config/git/config&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our config file is &lt;em&gt;read-only&lt;/em&gt; and is a link to an obscure path in the
&lt;code class=&quot;language-text&quot;&gt;/nix/store&lt;/code&gt;. Home-manager does this to ensure that you don’t accidentally
edit your generated config files, since your changes would be overridden
next time you run &lt;code class=&quot;language-text&quot;&gt;home-manager switch&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ready to try something else? Let’s remove the homebrew copy of git:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ brew uninstall &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You’ll notice that &lt;code class=&quot;language-text&quot;&gt;git&lt;/code&gt; is still working:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt;
/Users/arkham/.nix-profile/bin/git

$ &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-al&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
lrwxr-xr-x &lt;span class=&quot;token number&quot;&gt;69&lt;/span&gt; root  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; Jan  &lt;span class=&quot;token number&quot;&gt;1970&lt;/span&gt; /Users/arkham/.nix-profile/bin/
&lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/ampvjly5y69drxcxyipjfzk2xghwn94i-home-manager
-path/bin/git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Oh god, these symlinks are EVERYWHERE.&lt;/p&gt;
&lt;h2 id=&quot;bring-on-the-heat&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bring-on-the-heat&quot; aria-label=&quot;bring on the heat permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Bring on the heat&lt;/h2&gt;
&lt;p&gt;Now we’re going to do the unthinkable. We’re going to move our precious
shell configuration inside &lt;code class=&quot;language-text&quot;&gt;home-manager&lt;/code&gt;. &lt;em&gt;Yes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;First let’s make sure we are in the right directory:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~/.config/nixpkgs&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I’m going to show you how to do it for Bash and Zsh. You can choose one:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; ~/.bashrc bashrc
$ &lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; ~/.bash_profile bash_profile

$ &lt;span class=&quot;token function&quot;&gt;cp&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; ~/.zshrc zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can change our &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stateVersion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;packages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sl
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bashInteractive &lt;span class=&quot;token comment&quot;&gt;# don&apos;t ask me why&lt;/span&gt;&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;git &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    includes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;~/.config/nixpkgs/gitconfig&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    profileExtra &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./bash_profile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    initExtra &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./bashrc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zsh &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    initExtra &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./zshrc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ready? Go! &lt;code class=&quot;language-text&quot;&gt;home-manager switch -b bak&lt;/code&gt; 😱&lt;/p&gt;
&lt;p&gt;If you open a new shell, you’ll see (&lt;em&gt;surprise!&lt;/em&gt;) that everything is still
working, and all your customizations are still there. The only difference
is that those configuration files are now symlinks to the Nix store.&lt;/p&gt;
&lt;p&gt;Note that by default your terminal will still run the shell provided by
the OS. In my terminal, I customized the starting shell to be the one
provided by Nix:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9a3cb76f66a4d754b654a8ef6eafd63a/50517/iterm2-settings.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 71.51898734177216%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABYlAAAWJQFJUiTwAAADNklEQVR42p2SzW7bRhSFJ07h2JVix3ZTO7JoSYkTy6JIUyJnSPFHIocUSf1Ylu20Tp120z5BDLRv1z5GtMk2ELwpgi5rjk5BtUVdoKsuPpyZO8DBuXcu8bdfrL4NzR/6jvmjz4x33GI33KI3gZmTn9nNNI5uJhFf1v58v4dJ3wUd6yfH9r+v7G6vkr2NJ6XUYb8N/S5GvoeYJ0gDjkHXwSjoIXZtjPwuxkEPiecgtBi4SREw4x4UHjM/lb58uk8eF9YlW1PmXkuBcyLfuS01czUlc0/kzNWa2etBnJ3yXta3WZa4nSy2WRY7VpY4VhbbZtbvsN+HXQeupnwsrq0dkI21R2WzWb/tOyZMtSGMxqsFlY8WuTL5aOEb2mIceItpP1h8fTpaxEG84LS1iCxjSWjqgtM2Ompj/qRYkEhx9bOyqTRueYeBNo+FIddzRa5MruepEVkUZ2EPl2kf0zjCiHOknoPYNhHQtrhIIoQWnRNCJLL3xU5ZO6zeytIzNA9KolkpoVnZR343jl4gH0VPV5FyjrevL/DNZICz0QR910bqMvhUE6FloGdo80cPVySyu7Nd1g5rt2pNglqTxF8KpVoGrR/CUxTwdgsT38fVYIiLKMI5D3AZRRiHQ4QGFaGuw1Hk+ebjz/OEfxuWodwzzFNaR3V8N5jiKh1jYHNMewEmno8zL8CZ5yOxuojaTMQGQ18151vF4r8TKtV7htV9dI6O8SYc4ioZY+wleBMPcT04xXU6xnV6inHHRWJYImUdJCedfwxbL/+75XyGk6CHr9I+Rp4DbrQRUgMRo4gthr7JwA1dhIYOR5Xnm8V1iew93SmrzyvzvMVmZf9OPiiJnIb0TOivaqJrtMX5aCQu00ikXVskriV6xomw1YZwNFk4WvPOazVhNesftzY2JLJVLEi22vjEjl8uP8FRG8tVsZXjJfnSfnsxxTTycR6HOIv85bpw1kZo6ghztShsTfl1q7B2QB4QsuvqrV+oXP/Qrh++95k+C21r1mP6zGjUZ3ZLnbm6NrNUeRZYdMZtc/mW1zyjNfN07b1L6QdNVn4uPCC7ZL1QfEgI2SOE1Agh1f9JbemxsrnyB9NGfFaimrLjAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;iTerm2 custom terminal settings&quot;
        title=&quot;&quot;
        src=&quot;/static/9a3cb76f66a4d754b654a8ef6eafd63a/f058b/iterm2-settings.png&quot;
        srcset=&quot;/static/9a3cb76f66a4d754b654a8ef6eafd63a/c26ae/iterm2-settings.png 158w,
/static/9a3cb76f66a4d754b654a8ef6eafd63a/6bdcf/iterm2-settings.png 315w,
/static/9a3cb76f66a4d754b654a8ef6eafd63a/f058b/iterm2-settings.png 630w,
/static/9a3cb76f66a4d754b654a8ef6eafd63a/40601/iterm2-settings.png 945w,
/static/9a3cb76f66a4d754b654a8ef6eafd63a/78612/iterm2-settings.png 1260w,
/static/9a3cb76f66a4d754b654a8ef6eafd63a/50517/iterm2-settings.png 2060w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But what is the advantage of letting home-manager take care of those files?
Aren’t those glorified symlinks after all?
Isn’t it all pointless?&lt;/p&gt;
&lt;p&gt;Let me show you &lt;em&gt;why&lt;/em&gt; this is VERY NICE.&lt;/p&gt;
&lt;p&gt;Let’s change our &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt; again:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stateVersion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;packages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sl
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bashInteractive
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;git &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    includes &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; path &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;~/.config/nixpkgs/gitconfig&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;bash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    profileExtra &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./bash_profile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    initExtra &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./bashrc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zsh &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    initExtra &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./zshrc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fzf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zoxide &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;direnv &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    nix&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;direnv&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;fzf&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;zoxide&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;direnv&lt;/code&gt; are programs that need to be hooked in your
shell. So normally you’d have to install the program and then edit your
shell config to load them up. Instead, home-manager will do that for you
now. Neat, right?&lt;/p&gt;
&lt;p&gt;Have you noticed that last line that says &lt;code class=&quot;language-text&quot;&gt;nix-direnv.enable = true&lt;/code&gt;? That
single line will cache your direnv activated nix shells and make them super
fast. That’s the advantage of using home-manager, you get all this stuff
for free, with only one line of code. Do you want a nicer diffing
experience in git? Enable &lt;a href=&quot;https://nix-community.github.io/home-manager/options.html#opt-programs.git.delta.enable&quot;&gt;this
option&lt;/a&gt;
in your &lt;code class=&quot;language-text&quot;&gt;programs.git&lt;/code&gt; block and you’re done. Do you want fzf and tmux to
work nicer together? Enable this &lt;a href=&quot;https://nix-community.github.io/home-manager/options.html#opt-programs.fzf.tmux.enableShellIntegration&quot;&gt;other
option&lt;/a&gt;
and you’re set.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mipmip.github.io/home-manager-option-search/&quot;&gt;This page&lt;/a&gt; is
very useful to look at which programs are included in home-manager and
which options are supported. You can view the same information locally by
running:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;man&lt;/span&gt; home-configuration.nix&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also check my Nix configuration on
&lt;a href=&quot;https://github.com/Arkham/dotfiles.nix&quot;&gt;Github&lt;/a&gt; for inspiration.&lt;/p&gt;
&lt;h3 id=&quot;i-like-this-what-do-i-do-next&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#i-like-this-what-do-i-do-next&quot; aria-label=&quot;i like this what do i do next permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;I like this. What do I do next?&lt;/h3&gt;
&lt;p&gt;You can start by moving more and more packages from homebrew to
home-manager. Take it easy, as they can coexist peacefully. For example,
you could check out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how to port your &lt;a href=&quot;https://github.com/Arkham/dotfiles.nix/blob/ba85362abf3a442b327d0b8fbb4691de5649cf40/git.nix&quot;&gt;git&lt;/a&gt; configuration&lt;/li&gt;
&lt;li&gt;how to port your
&lt;a href=&quot;https://github.com/Arkham/dotfiles.nix/blob/ba85362abf3a442b327d0b8fbb4691de5649cf40/vim.nix&quot;&gt;vim&lt;/a&gt; configuration&lt;/li&gt;
&lt;li&gt;how to port your
&lt;a href=&quot;https://github.com/Arkham/dotfiles.nix/blob/ba85362abf3a442b327d0b8fbb4691de5649cf40/rest.nix#L9-L40&quot;&gt;bash&lt;/a&gt; configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;how-do-i-update-all-my-packages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-do-i-update-all-my-packages&quot; aria-label=&quot;how do i update all my packages permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How do I update all my packages?&lt;/h3&gt;
&lt;p&gt;Go inside &lt;code class=&quot;language-text&quot;&gt;~/.config/nixpkgs&lt;/code&gt; and run&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nix flake update

$ home-manager switch&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;how-do-i-manage-multiple-machines-with-different-architectures&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-do-i-manage-multiple-machines-with-different-architectures&quot; aria-label=&quot;how do i manage multiple machines with different architectures permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How do I manage multiple machines with different architectures?&lt;/h3&gt;
&lt;p&gt;Check out &lt;a href=&quot;https://github.com/Arkham/dotfiles.nix/blob/ba85362abf3a442b327d0b8fbb4691de5649cf40/flake.nix#L18-L38&quot;&gt;this
section&lt;/a&gt; of my &lt;code class=&quot;language-text&quot;&gt;flake.nix&lt;/code&gt;. You can create multiple blocks where
&lt;code class=&quot;language-text&quot;&gt;homeConfigurations&lt;/code&gt; is followed by &lt;code class=&quot;language-text&quot;&gt;YOUR_USER@YOUR_HOSTNAME&lt;/code&gt;. Remember you
can always find your user with &lt;code class=&quot;language-text&quot;&gt;whoami&lt;/code&gt; and your hostname with &lt;code class=&quot;language-text&quot;&gt;hostname&lt;/code&gt;.
As you can see, I’ve extracted the shared configuration inside a &lt;code class=&quot;language-text&quot;&gt;withArch&lt;/code&gt; helper
function.&lt;/p&gt;
&lt;h3 id=&quot;how-do-i-manage-multiple-machines-with-different-setups&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-do-i-manage-multiple-machines-with-different-setups&quot; aria-label=&quot;how do i manage multiple machines with different setups permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How do I manage multiple machines with different setups?&lt;/h3&gt;
&lt;p&gt;The easiest way is to have multiple &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt; files, one for each machine:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Home Manager configuration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  inputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nixos/nixpkgs/nixpkgs-unstable&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nix-community/home-manager&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      inputs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;follows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nixpkgs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  outputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    defaultPackage &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;x86_64-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x86_64&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;darwin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;aarch64-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;aarch64&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;darwin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    homeConfigurations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;alice@wonderland&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;/span&gt;      home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeManagerConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;x86_64&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;darwin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        modules &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./home-alice.nix&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    homeConfigurations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;bob@bikinibottom&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;/span&gt;      home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeManagerConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;aarch64&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;darwin&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        modules &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./home-bob.nix&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then in each file you can share modules, helper functions, or whatever your
heart desires.&lt;/p&gt;
&lt;h3 id=&quot;i-dont-want-to-use-unstable-software-how-do-i-use-the-stable-version&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#i-dont-want-to-use-unstable-software-how-do-i-use-the-stable-version&quot; aria-label=&quot;i dont want to use unstable software how do i use the stable version permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;I don’t want to use unstable software. How do I use the stable version?&lt;/h3&gt;
&lt;p&gt;In your &lt;code class=&quot;language-text&quot;&gt;flake.nix&lt;/code&gt; do this in your &lt;code class=&quot;language-text&quot;&gt;inputs&lt;/code&gt; block:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Home Manager configuration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  inputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nixos/nixpkgs/nixpkgs-22.11-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nix-community/home-manager/release-22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      inputs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;follows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nixpkgs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
  outputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
    arch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;x86_64-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# or aarch64-darwin&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
      home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    homeConfigurations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;YOUR_USER &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# REPLACE ME&lt;/span&gt;
      home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeManagerConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        modules &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./home.nix&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;ive-changed-my-mind-how-do-i-get-both-stable-and-unstable&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ive-changed-my-mind-how-do-i-get-both-stable-and-unstable&quot; aria-label=&quot;ive changed my mind how do i get both stable and unstable permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;I’ve changed my mind. How do I get both stable and unstable?&lt;/h3&gt;
&lt;p&gt;In your &lt;code class=&quot;language-text&quot;&gt;flake.nix&lt;/code&gt; do this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  description &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Home Manager configuration&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  inputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nixos/nixpkgs/nixpkgs-22.11-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nix-community/home-manager/release-22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      inputs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;follows &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nixpkgs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    nixpkgs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;unstable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;      url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;github:nixos/nixpkgs/nixpkgs-unstable&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;  outputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nixpkgs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;unstable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
      arch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;x86_64-darwin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# or aarch64-darwin&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
        home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;defaultPackage&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

      homeConfigurations&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;YOUR_USER &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# REPLACE ME&lt;/span&gt;
        home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lib&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeManagerConfiguration &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          modules &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./home.nix&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          extraSpecialArgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;            pkgs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;unstable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nixpkgs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;unstable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;legacyPackages&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token antiquotation important&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;arch&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then in your &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt; you can do:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pkgs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;unstable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;username &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;homeDirectory &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;/Users/arkham&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stateVersion &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;22.11&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  programs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;home&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;manager&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;enable &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;packages &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sl
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    pkgs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;unstable&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;cowsay&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you can run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cowthink &lt;span class=&quot;token string&quot;&gt;&quot;Nix is pretty neat.&quot;&lt;/span&gt;
 _____________________
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; Nix is pretty neat. &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 ---------------------
        o   ^__^
         o  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;oo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;_______
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;__&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;       &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;/&lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;----w &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;i-need-a-config-file-which-is-unsupported-how-do-i-symlink-it-into-my-home&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#i-need-a-config-file-which-is-unsupported-how-do-i-symlink-it-into-my-home&quot; aria-label=&quot;i need a config file which is unsupported how do i symlink it into my home permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;I need a config file which is unsupported. How do I symlink it into my home?&lt;/h3&gt;
&lt;p&gt;Move the file inside &lt;code class=&quot;language-text&quot;&gt;~/.config/nixpkgs&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; .inputrc ~/.config/nixpkgs/inputrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then add a section like this to your &lt;code class=&quot;language-text&quot;&gt;home.nix&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.inputrc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;source &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./inputrc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If the config is very short you can also pass it inline:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;home&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;file&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;.gemrc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gem: --no-ri --no-rdoc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;ive-made-a-terrible-mistake-and-screwed-up-my-configs-halp&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ive-made-a-terrible-mistake-and-screwed-up-my-configs-halp&quot; aria-label=&quot;ive made a terrible mistake and screwed up my configs halp permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;I’ve made a terrible mistake and screwed up my configs. Halp!&lt;/h3&gt;
&lt;p&gt;No big deal. Run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ home-manager generations
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-14 &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;:59 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/d8xwz7hik6i2iji4wl9py7p6rxn2vn56-home-manager-generation
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-13 &lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;:07 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/sxgdyj9lbx496rczgn7rig2vkjly6nwj-home-manager-generation
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-13 01:13 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/wdllhq7pf0sghn3kb0w1hjqc9962i02j-home-manager-generation
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-12 00:01 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/fm9bg8phff5zm0hp3mp5safk9v6dgdrc-home-manager-generation
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-11 &lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;:28 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/wdllhq7pf0sghn3kb0w1hjqc9962i02j-home-manager-generation
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-11 &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;:59 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/i6979nf0135r6qid4dpq2m3vmy177k1w-home-manager-generation
&lt;span class=&quot;token number&quot;&gt;2023&lt;/span&gt;-02-11 &lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;:01 &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; /nix/store/6iybn1scyl9yh0xb2scp4hfza65xnnfa-home-manager-generation&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each symlink points to an immutable copy of a previous home configuration.
Look at the timestamp, grab the Nix store path, append &lt;code class=&quot;language-text&quot;&gt;/activate&lt;/code&gt;, and run
it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ /nix/store/fm9bg8phff5zm0hp3mp5safk9v6dgdrc-home-manager-
generation/activate
Starting Home Manager activation
Activating checkFilesChanged
Activating checkLaunchAgents
Activating checkLinkTargets
Activating writeBoundary
Activating copyFonts
Activating installPackages
replacing old &lt;span class=&quot;token string&quot;&gt;&apos;home-manager-path&apos;&lt;/span&gt;
installing &lt;span class=&quot;token string&quot;&gt;&apos;home-manager-path&apos;&lt;/span&gt;
Activating linkGeneration
Cleaning up orphan links from /Users/arkham
Creating profile generation &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;
Creating home &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; links &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; /Users/arkham
Activating onFilesChange
Activating setupLaunchAgents&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;🎉 🎉 🎉&lt;/p&gt;
&lt;h3 id=&quot;nix-is-taking-a-lot-of-space-on-my-machine&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nix-is-taking-a-lot-of-space-on-my-machine&quot; aria-label=&quot;nix is taking a lot of space on my machine permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nix is taking a lot of space on my machine.&lt;/h3&gt;
&lt;p&gt;Unfortunately that is a side effect of the Nix philosophy of tracking &lt;strong&gt;every&lt;/strong&gt;
dependencies’ dependencies. You can remove programs that you installed in
the past by running:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nix-collect-garbage &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;this-is-bad-how-do-i-uninstall-it&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#this-is-bad-how-do-i-uninstall-it&quot; aria-label=&quot;this is bad how do i uninstall it permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;This is bad. How do I uninstall it?&lt;/h3&gt;
&lt;p&gt;Uninstall home-manager:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ home-manager uninstall&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Restore your backups in your home directory:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; ~

$ &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; .gitconfig.bak .gitconfig

$ &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; .bashrc.bak .bashrc
$ &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; .bash_profile.bak .bash_profile

$ &lt;span class=&quot;token function&quot;&gt;mv&lt;/span&gt; .zshrc.bak .zshrc&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then follow &lt;a href=&quot;https://nixos.org/manual/nix/stable/installation/installing-binary.html#macos&quot;&gt;this
guide&lt;/a&gt;
to uninstall Nix.&lt;/p&gt;
&lt;h3 id=&quot;is-homebrew-completely-useless-now&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#is-homebrew-completely-useless-now&quot; aria-label=&quot;is homebrew completely useless now permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Is homebrew completely useless now?&lt;/h3&gt;
&lt;p&gt;No, I still use it to install casks. ⚰️&lt;/p&gt;
&lt;h3 id=&quot;still-reading&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#still-reading&quot; aria-label=&quot;still reading permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Still reading?&lt;/h3&gt;
&lt;p&gt;Fun fact: this blog uses
&lt;a href=&quot;https://github.com/Arkham/juliu.is/blob/main/flake.nix&quot;&gt;Nix flakes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Many thanks to the wonderful human beings that have read earlier versions
of this post: Pedro Piñera Buendía, Isaac Roldán, Fabrizio Monti, Andrew MacMurray,
Austin Erlandson, and Georges Boris.&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Peeling zeroes in Idris]]></title><description><![CDATA[🎶 We’re no strangers to lists, you know the rules and so do I 🎶 Anyway, here’s one: If we want to get an element from a list at a specific…]]></description><link>https://juliu.is/peeling-zeroes/</link><guid isPermaLink="false">https://juliu.is/peeling-zeroes/</guid><pubDate>Thu, 28 Oct 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;🎶 We’re no strangers to lists, you know the rules and so do I 🎶&lt;/p&gt;
&lt;p&gt;Anyway, here’s one:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;George&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Ringo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we want to get an element from a list at a specific index, we can
reach for a function like &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which we would use like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The reason this function returns a &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; is that we could pass &lt;em&gt;any&lt;/em&gt;
number to it. It seems thus inescapable that we need to handle the case
when the given number is “out of bounds”. It seems impossible to conjure a
function which at the same time is safe and behaves like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This seems peculiar because unless something quite monstrous happens we
know that there will be no further changes to the Beatles lineup. So the
problem is that &lt;strong&gt;we&lt;/strong&gt; know this but the type system doesn’t, and it has
to treat that list as it would treat any other list.&lt;/p&gt;
&lt;p&gt;Is there no way out?&lt;/p&gt;
&lt;h2 id=&quot;enter-idris&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#enter-idris&quot; aria-label=&quot;enter idris permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Enter Idris&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.idris-lang.org/&quot;&gt;Idris&lt;/a&gt; there is another data structure that can describe lists called &lt;code class=&quot;language-text&quot;&gt;Vect&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;George&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Ringo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s going on here?&lt;/p&gt;
&lt;p&gt;The type also contains information about the length of the list. Let’s see
what happens if we forget one of the Fab Four:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;George&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Idris complains:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;unifying&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Mismatch&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;between&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;39&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;--6:40&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Data.Vect&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;George&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                                           &lt;span class=&quot;token operator&quot;&gt;^&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Don’t worry too much about the specifics of the error message, just look at
that little caret that Idris puts at the end. It’s almost as the compiler
is telling us “Hey, something’s missing there”.&lt;/p&gt;
&lt;p&gt;With this data structure we can write something like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Vect.index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we get the raw value, no &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; nonsense here. What about when
we pass a number that’s out of bounds?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;idris&quot;&gt;&lt;pre class=&quot;language-idris&quot;&gt;&lt;code class=&quot;language-idris&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Vect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Can&apos;&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;implementation&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;for&lt;/span&gt;
       &lt;span class=&quot;token constant&quot;&gt;IsJust&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;integerToFin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Interactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;--1:14&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Vect&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Woah, now the compiler understands. &lt;em&gt;Cool&lt;/em&gt;. But what’s the type
signature of this &lt;code class=&quot;language-text&quot;&gt;index&lt;/code&gt; function?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Vect.index&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;Vect.index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Vect&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;len&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uh, what that’s &lt;code class=&quot;language-text&quot;&gt;Fin&lt;/code&gt; type? It describes a natural number strictly less
than some bound. The name comes from “finite sets”, i.e. sets that have a
finite number of elements. Its definition is:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Ok&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;We might need to take a little step back to unpack it.&lt;/p&gt;
&lt;h2 id=&quot;natura-artis-magistra&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#natura-artis-magistra&quot; aria-label=&quot;natura artis magistra permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Natura, artis magistra&lt;/h2&gt;
&lt;p&gt;Natural numbers are integers greater or equal than zero. A neat trick to
represent them is to create a recursive type:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Z&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where &lt;code class=&quot;language-text&quot;&gt;Z&lt;/code&gt; represents zero, while &lt;code class=&quot;language-text&quot;&gt;S Nat&lt;/code&gt; represents the &lt;em&gt;successor&lt;/em&gt; of a
certain natural number.&lt;/p&gt;
&lt;p&gt;Using this type we can construct the following values:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;plain&quot;&gt;&lt;pre class=&quot;language-plain&quot;&gt;&lt;code class=&quot;language-plain&quot;&gt;Z           == 0
S Z         == 1
S (S Z)     == 2
S (S (S Z)) == 3&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can see that Idris does a little bit of magic under the hood so that we
can write &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;S Z&lt;/code&gt;. &lt;em&gt;Neat&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A somewhat interesting fact is that we can also get the &lt;em&gt;previous&lt;/em&gt; natural
number by removing a layer of &lt;code class=&quot;language-text&quot;&gt;S&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Z&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;prev&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that we know how to express natural numbers in Idris, we can take a
look at our finite subsets of natural numbers.&lt;/p&gt;
&lt;h2 id=&quot;the-meat-and-potatoes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-meat-and-potatoes&quot; aria-label=&quot;the meat and potatoes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Meat and Potatoes&lt;/h2&gt;
&lt;p&gt;Let’s look at that definition again:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This looks a tad different from the previous &lt;code class=&quot;language-text&quot;&gt;data Nat = Z | S Nat&lt;/code&gt;
definition, but it’s quite close:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We are defining a function called &lt;code class=&quot;language-text&quot;&gt;Fin&lt;/code&gt; that takes a natural number and returns a type.&lt;/li&gt;
&lt;li&gt;One possible constructor is &lt;code class=&quot;language-text&quot;&gt;FZ&lt;/code&gt;, which stands for “finite zero”.&lt;/li&gt;
&lt;li&gt;The other constructor is &lt;code class=&quot;language-text&quot;&gt;FS&lt;/code&gt;, which takes an existing &lt;code class=&quot;language-text&quot;&gt;Fin&lt;/code&gt; and returns its successor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From this explanation it’s not clear &lt;em&gt;how&lt;/em&gt; we are restricting these natural numbers,
so let’s play around with some finite numbers. Since a literal &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt; can
be an &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;, a &lt;code class=&quot;language-text&quot;&gt;Nat&lt;/code&gt;, and many other things, we have to use the special
&lt;code class=&quot;language-text&quot;&gt;the&lt;/code&gt; function to tell Idris which specific type we want:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So everything is good when we ask for a &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt; in &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt;, the set of natural
numbers strictly less than &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;. How about this?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It blows up!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Error: Can&apos;t find an implementation
for IsJust (integerToFin 0 0).

(Interactive):1:13--1:14
 1 | the (Fin 0) 0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Why is this happening? By definition the minimum value we can create is
&lt;code class=&quot;language-text&quot;&gt;FZ&lt;/code&gt;. The type of this value is &lt;code class=&quot;language-text&quot;&gt;Fin (S k)&lt;/code&gt;, and by definition &lt;code class=&quot;language-text&quot;&gt;S k&lt;/code&gt; must
be greater than zero. So this means that the smallest set we can create is
&lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt;, which is the set that only contains zero.&lt;/p&gt;
&lt;p&gt;Let’s look at &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt;, the set that contains &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As expected, the zeroes in &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt; are different:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;When&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;unifying&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Mismatch&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;between&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Interactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;--1:14&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
     &lt;span class=&quot;token operator&quot;&gt;^^^^^^^^^^^^^&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Ok, time for a little surprise. Look at these values again:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Those &lt;code class=&quot;language-text&quot;&gt;FZ&lt;/code&gt; values are not the same! The first one is of type &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt;, while
the second one is of type &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt;. This makes sense when we look at the
type of the &lt;code class=&quot;language-text&quot;&gt;FS&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or making it more concrete:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;we get a &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt; of type &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;we apply &lt;code class=&quot;language-text&quot;&gt;FS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;we get a &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; of type &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How would we get a &lt;code class=&quot;language-text&quot;&gt;2&lt;/code&gt; of type &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt;? We would need to apply the &lt;code class=&quot;language-text&quot;&gt;FS&lt;/code&gt;
function twice, going from &lt;code class=&quot;language-text&quot;&gt;Fin 0&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt;, right?&lt;/p&gt;
&lt;p&gt;The problem is, we simply cannot do that.&lt;/p&gt;
&lt;p&gt;The smallest valid finite set is &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt;, which means we just &lt;em&gt;cannot&lt;/em&gt;
apply that function twice to create that value. You can only apply it once,
giving us &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;, which is the largest element in &lt;code class=&quot;language-text&quot;&gt;Fin 2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we look at &lt;code class=&quot;language-text&quot;&gt;Fin 3&lt;/code&gt;, things start making more sense:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Can&lt;/span&gt;&apos;&lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;implementation&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IsJust&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;integerToFin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Interactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;--1:14&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s like we’re starting with this beefy zero, and we need to peel a layer
to be able to create the next number. Then we keep peeling and peeling, up
until we just can’t peel anything anymore. &lt;code class=&quot;language-text&quot;&gt;Fin 1&lt;/code&gt; is the end of all hopes,
the last laugh, the final curtain.&lt;/p&gt;
&lt;h2 id=&quot;and-now-for-something-completely-different&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#and-now-for-something-completely-different&quot; aria-label=&quot;and now for something completely different permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;And Now for Something Completely Different&lt;/h2&gt;
&lt;p&gt;If you’ve followed so far, you’re in for a treat 🍭&lt;/p&gt;
&lt;p&gt;We’ve talked a lot about &lt;code class=&quot;language-text&quot;&gt;Vect&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Fin&lt;/code&gt;, but you don’t need any of that
to reap the benefits we’ve talked about! Let’s go back to lists:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;George&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Ringo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Look at this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What??? How is it possible it just returns a value, no &lt;code class=&quot;language-text&quot;&gt;Maybe&lt;/code&gt; in sight?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Can&lt;/span&gt;&apos;&lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;find&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;implementation&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Paul&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;George&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Ringo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Interactive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;--1:24&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;theBeatles&lt;/span&gt;
     &lt;span class=&quot;token operator&quot;&gt;^^^^^^^^^^^^^^^^^^^^^^^&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just &lt;em&gt;how&lt;/em&gt;. Let’s dig in:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.index&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;List.index&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we look at the third argument we notice some curly braces around it. I
won’t go too much in detail, but that’s an &lt;a href=&quot;https://docs.idris-lang.org/en/latest/tutorial/miscellany.html#implicit-arguments&quot;&gt;implicit
argument&lt;/a&gt;
that doesn’t need to be passed in when calling the function.&lt;/p&gt;
&lt;p&gt;The interesting bit for us is that &lt;code class=&quot;language-text&quot;&gt;InBounds&lt;/code&gt; type:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;InFirst&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;InLater&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That looks complicated. But how about we compare it to this?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nat&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;where&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;FZ&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;FS&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Fin&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;There is a base case. We use &lt;code class=&quot;language-text&quot;&gt;x :: xs&lt;/code&gt; to signal that the list must not be empty, so that we can never get an &lt;code class=&quot;language-text&quot;&gt;InFirst&lt;/code&gt; value of type &lt;code class=&quot;language-text&quot;&gt;InBounds 0 []&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;There is a function that we can call recursively to peel a layer. In this case, not only do we go from &lt;code class=&quot;language-text&quot;&gt;k&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;S k&lt;/code&gt;, but we also specify that the list gets an extra element in front.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you squint a bit, you’ll see it’s the exact type trick we’ve seen
before. If we tried to call &lt;code class=&quot;language-text&quot;&gt;List.index 1 [&quot;John&quot;]&lt;/code&gt; we’d have to find a way
to call the &lt;code class=&quot;language-text&quot;&gt;InLater&lt;/code&gt; function to peel off a layer. Or more concretely:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;InLater&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;S&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- becomes&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;InLater&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InBounds&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem is constructing that &lt;code class=&quot;language-text&quot;&gt;InBounds 0 []&lt;/code&gt;. By definition &lt;code class=&quot;language-text&quot;&gt;InFirst&lt;/code&gt;
has to be &lt;code class=&quot;language-text&quot;&gt;InBounds 0 (x :: xs)&lt;/code&gt;, so we simply cannot create such value.
Thus the type system cannot find a valid implementation of &lt;code class=&quot;language-text&quot;&gt;InBounds 1 [&quot;John&quot;]&lt;/code&gt;,
which is exactly the error message Idris prints out. &lt;em&gt;QED&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this adventure in the land of zeroes and dependent
types.&lt;/p&gt;
&lt;p&gt;Fin 1.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Ditch your version manager]]></title><description><![CDATA[You probably use a variety of tools to manage your Ruby, Node, Python,
Elixir versions, such as rvm,
rbenv,
nvm, or asdf.
They all work…]]></description><link>https://juliu.is/ditch-your-version-manager/</link><guid isPermaLink="false">https://juliu.is/ditch-your-version-manager/</guid><pubDate>Fri, 17 Sep 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You probably use a variety of tools to manage your Ruby, Node, Python,
Elixir versions, such as &lt;a href=&quot;http://rvm.io/&quot;&gt;rvm&lt;/a&gt;,
&lt;a href=&quot;https://github.com/rbenv/rbenv&quot;&gt;rbenv&lt;/a&gt;,
&lt;a href=&quot;https://github.com/nvm-sh/nvm&quot;&gt;nvm&lt;/a&gt;, or &lt;a href=&quot;https://asdf-vm.com/&quot;&gt;asdf&lt;/a&gt;.
They all work reasonably well, right?&lt;/p&gt;
&lt;p&gt;Well, not quite.&lt;/p&gt;
&lt;p&gt;The fundamental issue is that many programs depend on &lt;em&gt;other&lt;/em&gt; programs being
present in the same system. For many years, if you wanted to install
&lt;a href=&quot;https://nokogiri.org/&quot;&gt;nokogiri&lt;/a&gt;, a popular XML parser written in Ruby,
you’d have to remember to install &lt;code class=&quot;language-text&quot;&gt;libxml&lt;/code&gt; beforehand. Furthermore, some of
these programs depend on OS-specific configurations, such as libraries
shipped with Mac OS or Linux.&lt;/p&gt;
&lt;p&gt;It’s not uncommon to check out a project and having to install a plethora
of libraries and tools, and having to hope that the versions that you
installed are compatible with the ones used by the original authors. Then
you’d have to figure out a way to install an older version of a specific
package.&lt;/p&gt;
&lt;p&gt;I can hear what you’re wondering now: what about
&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;? The idea of having a container image
that contains all your dependencies sounds very promising indeed. The issue
with docker images is that all those dependencies are still intertwined,
only the whole dependency tree has become &lt;em&gt;invisible&lt;/em&gt;: for example, if the
version of Ubuntu you are using has reached its End-Of-Life, you will have
to manually untangle all the dependencies and update everything in one go.
If you’re working on a large project with many dependencies, please do accept
my condolences.&lt;/p&gt;
&lt;p&gt;My ideal dependency manager would allow me to specify &lt;strong&gt;each and every&lt;/strong&gt;
dependency that is required to work on my projects. It should be easily
reproducible, declarative and easy to upgrade.&lt;/p&gt;
&lt;p&gt;Does it sound too good to be true?&lt;/p&gt;
&lt;h2 id=&quot;welcome-to-the-jungle&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#welcome-to-the-jungle&quot; aria-label=&quot;welcome to the jungle permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Welcome to the jungle&lt;/h2&gt;
&lt;p&gt;Let me introduce you to &lt;a href=&quot;https://nixos.org/&quot;&gt;Nix&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nix is a tool that takes a unique approach to package management and system configuration. Learn how to make reproducible, declarative and reliable systems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s try it out.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;sh&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-L&lt;/span&gt; https://nixos.org/nix/install&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nix-env &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
nix-env &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Nix&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2.3&lt;/span&gt;.10&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Before we can start on our first project we will need to install
&lt;a href=&quot;https://direnv.net/&quot;&gt;direnv&lt;/a&gt;, a tool which will let us build
a custom environment in a specific folder. You’ll need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;nix-env -iA nixpkgs.direnv&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://direnv.net/docs/hook.html&quot;&gt;hook direnv into your shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;restart your shell&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we’re ready and raring to go! 🏄‍♀️&lt;/p&gt;
&lt;p&gt;Let’s create a new folder:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;mkdir&lt;/span&gt; nix_hello_world &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;cd&lt;/span&gt; nix_hello_world

$ hello
-bash: hello: &lt;span class=&quot;token builtin class-name&quot;&gt;command&lt;/span&gt; not found&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, no &lt;code class=&quot;language-text&quot;&gt;hello&lt;/code&gt; command is available yet.&lt;/p&gt;
&lt;p&gt;We can write our first configuration in a file called &lt;code class=&quot;language-text&quot;&gt;default.nix&lt;/code&gt;. We’ll
be using the &lt;a href=&quot;https://nixos.wiki/wiki/Nix_Expression_Language&quot;&gt;Nix Expression
Language&lt;/a&gt;, a pure, lazy,
functional programming language. Exciting times!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
  pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nixpkgs&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mkShell &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  buildInputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hello &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can tell direnv to load this file and update our environment.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;use nix&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; .envrc
direnv: error /Users/arkham/Desktop/nix_hello_world/.envrc
is blocked. Run &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;direnv allow&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; to approve its content

$ direnv allow
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;loads of nix output&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

$ hello
Hello, world&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;🎉&lt;/p&gt;
&lt;p&gt;What did we do?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;we imported the whole set of packages provided by Nix and called it &lt;code class=&quot;language-text&quot;&gt;pkgs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;we used the &lt;code class=&quot;language-text&quot;&gt;mkShell&lt;/code&gt; built-in function to create a new environment where
we can use Nix programs&lt;/li&gt;
&lt;li&gt;we specify we want the GNU &lt;code class=&quot;language-text&quot;&gt;hello&lt;/code&gt; program&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What if we wanted ruby? Couldn’t be simpler:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
  pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nixpkgs&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mkShell &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  buildInputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hello
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ruby
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By saving this file and returning to your shell (you might need to press
&lt;code class=&quot;language-text&quot;&gt;Enter&lt;/code&gt; to let direnv reload), Nix will pick up the change and install the
new dependency.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
ruby &lt;span class=&quot;token number&quot;&gt;2.7&lt;/span&gt;.4p191 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;-07-07&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x86_64-darwin17&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

$ &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; ruby
/nix/store/r6siyyqmnidkn2y8y5hl7payykb51kb0-ruby-2.7.4/bin/ruby&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s with that super long path? Don’t worry, it’s just how Nix stores its
data (&lt;em&gt;waves hands.. iMmUTaBIlitY&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;What if we needed node?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
  pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nixpkgs&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mkShell &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  buildInputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hello
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ruby
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nodejs
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
v14.17.2

$ &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;
/nix/store/zj1sqykb3s5a0fakm94qwz7fg6g2zxpm-nodejs-14.17.2/bin/node&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You see the pattern here.&lt;/p&gt;
&lt;p&gt;How about a different version of Ruby or Node? Let’s say that our project
depends on Ruby 2.6 and Node 10. We can &lt;a href=&quot;https://search.nixos.org/packages&quot;&gt;go and
search&lt;/a&gt; for those specific versions,
then change our &lt;code class=&quot;language-text&quot;&gt;default.nix&lt;/code&gt; accordingly:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
  pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nixpkgs&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mkShell &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  buildInputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hello
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ruby_2_6
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nodejs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;10_x
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;$ ruby --version
ruby 2.6.8p205 (2021-07-07) [x86_64-darwin17]

$ node --version
v10.24.1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;🎉&lt;/p&gt;
&lt;h2 id=&quot;some-bad-news&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-bad-news&quot; aria-label=&quot;some bad news permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some bad news&lt;/h2&gt;
&lt;p&gt;Unfortunately, if you tried to follow this article step by step, you’ll
have noticed that the versions of &lt;code class=&quot;language-text&quot;&gt;ruby&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;node&lt;/code&gt; you installed are
probably slightly different from the ones above.&lt;/p&gt;
&lt;p&gt;Wasn’t Nix supposed to give us &lt;em&gt;reproducible&lt;/em&gt; builds?&lt;/p&gt;
&lt;p&gt;Yes, but…&lt;/p&gt;
&lt;p&gt;All the software that we installed depends on the specific version of the
&lt;strong&gt;nixpkgs channel&lt;/strong&gt; that we installed on our system. We can check which
version that is by running:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nix repl
Welcome to Nix version &lt;span class=&quot;token number&quot;&gt;2.3&lt;/span&gt;.10. Type :? &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; help.

nix-repl&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;import &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;nixpkgs&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;.lib.version
&lt;span class=&quot;token string&quot;&gt;&quot;21.05pre292875.60563458051&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can then grab the commit part (the third segment) and view it on
&lt;a href=&quot;https://github.com/NixOS/nixpkgs/commit/60563458051&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If only we were pointing to the same commit, then we would have exactly the
same dependencies. But it would be foolish to require every project to
depend on the same version of nixpkgs. We need a way to specify this on a
per-project basis, right? We can use a tool called &lt;code class=&quot;language-text&quot;&gt;niv&lt;/code&gt; to do exactly
that.&lt;/p&gt;
&lt;h2 id=&quot;niv&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#niv&quot; aria-label=&quot;niv permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;niv&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/nmattia/niv&quot;&gt;niv&lt;/a&gt; lets us pin our dependencies to a
specific version, thus ensuring a full reproducibility of our setup.&lt;/p&gt;
&lt;p&gt;Let’s install it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ nix-env &lt;span class=&quot;token parameter variable&quot;&gt;-iA&lt;/span&gt; nixpkgs.niv&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can initialize a niv project:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ niv init --no-nixpkgs
Initializing
  Creating nix/sources.nix
  Creating nix/sources.json
  Not importing &lt;span class=&quot;token string&quot;&gt;&apos;nixpkgs&apos;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
Done: Initializing&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This command generates a couple files:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ tree
&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
└── nix
    ├── sources.json
    └── sources.nix

&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; directory, &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt; files&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;sources.json&lt;/code&gt; will contain all the dependencies that we’re going to
use.  Don’t worry about the &lt;code class=&quot;language-text&quot;&gt;sources.nix&lt;/code&gt; file, it’s mostly glue to allow
us to load a JSON file in Nix.&lt;/p&gt;
&lt;p&gt;For the sake of reproducibility, change your &lt;code class=&quot;language-text&quot;&gt;sources.json&lt;/code&gt; to look like
this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;nixpkgs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;branch&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;release-21.05&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;description&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nix Packages collection&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;homepage&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;owner&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;NixOS&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;repo&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nixpkgs&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;rev&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;5f244caea76105b63d826911b2a1563d33ff1cdc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;sha256&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1xlgynfw9svy7nvh9nkxsxdzncv9hg99gbvbwv3gmrhmzc3sar75&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tarball&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/NixOS/nixpkgs/archive/5f244caea76105b63d826911b2a1563d33ff1cdc.tar.gz&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;url_template&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://github.com/&amp;lt;owner&gt;/&amp;lt;repo&gt;/archive/&amp;lt;rev&gt;.tar.gz&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can create our top-level Nix configuration:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;nix&quot;&gt;&lt;pre class=&quot;language-nix&quot;&gt;&lt;code class=&quot;language-nix&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
  sources &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;./nix/sources.nix&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  pkgs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;import&lt;/span&gt; sources&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nixpkgs &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mkShell &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  buildInputs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hello
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ruby_2_6
    pkgs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nodejs&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;10_x
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Going back to the shell, you will see that the version of ruby has changed:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby &lt;span class=&quot;token parameter variable&quot;&gt;--version&lt;/span&gt;
ruby &lt;span class=&quot;token number&quot;&gt;2.6&lt;/span&gt;.7p197 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2021&lt;/span&gt;-04-05&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x86_64-darwin17&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Same for node:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt;
/nix/store/d08y5bbjq5pric7rwifim6bf4zvwmasc-nodejs-10.24.1/bin/node&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This time you’re going to see exactly the same versions!&lt;/p&gt;
&lt;p&gt;Another good news is that configuration will work &lt;strong&gt;forever&lt;/strong&gt;. That’s
right, the moment you commit this configuration to your project you will
ensure that it will never stop working.&lt;/p&gt;
&lt;p&gt;Need to install a new tool? Pop it in the Nix config.
Need to patch a program and make sure every one is using it? Create an
&lt;a href=&quot;https://nixos.wiki/wiki/Overlays&quot;&gt;overlay&lt;/a&gt;, pop it in the Nix file and
grab some pop corn. Need to update your packages? Run &lt;code class=&quot;language-text&quot;&gt;niv update&lt;/code&gt; and all
the new dependencies will be pulled in.&lt;/p&gt;
&lt;p&gt;Nix is a version manager for everything. You’ll never have to tell the new
colleague “oh right, you need to install this version of LLVM to get this
thing to work”. They can pull the repo, &lt;code class=&quot;language-text&quot;&gt;direnv allow&lt;/code&gt; and BAM,
fully-working, reproducible project setup.&lt;/p&gt;
&lt;p&gt;What are you waiting for?!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Elm at NoRedInk]]></title><description><![CDATA[At NoRedInk we have one of the largest Elm apps
in the world. It serves millions of teachers and students, and our frontend
code is almost…]]></description><link>https://juliu.is/elm-at-noredink/</link><guid isPermaLink="false">https://juliu.is/elm-at-noredink/</guid><pubDate>Wed, 28 Apr 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At &lt;a href=&quot;https://www.noredink.com&quot;&gt;NoRedInk&lt;/a&gt; we have one of the largest Elm apps
in the world. It serves millions of teachers and students, and our frontend
code is almost exclusively written in Elm. In this post, we will explore
the structure of our codebase and the patterns that we use to stay sane.
One of the most common questions I get about Elm is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Does it scale? And if so, how?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I don’t think that there can ever be a comprehensive answer to that
question, but I hope this post can be a useful reference to resources and
techniques we’ve used to solve real-world problems, so you can dig deeper
at your own leisure.&lt;/p&gt;
&lt;h2 id=&quot;table-of-contents&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#table-of-contents&quot; aria-label=&quot;table of contents permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Table of contents&lt;/h2&gt;
&lt;div class=&quot;table-of-contents&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#a-wild-monorepo-appears&quot;&gt;A wild monorepo appears&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#rails-conventions&quot;&gt;Rails conventions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#our-elm-programs&quot;&gt;Our Elm programs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#how-we-write-elm-files&quot;&gt;How we write Elm files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#nesting-the-elm-architecture&quot;&gt;Nesting the Elm Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#when-to-nest-tea-modules&quot;&gt;When to nest TEA modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#interacting-with-javascript&quot;&gt;Interacting with JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#testing&quot;&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#tooling&quot;&gt;Tooling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;a-wild-monorepo-appears&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-wild-monorepo-appears&quot; aria-label=&quot;a wild monorepo appears permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A wild monorepo appears&lt;/h2&gt;
&lt;p&gt;We have a glorious monorepo that contains all the services that power our
infrastructure. Our biggest service (which we affectionately call the
&lt;code class=&quot;language-text&quot;&gt;monolith&lt;/code&gt;) is written in Rails and contains most of our Elm code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cloc --include-ext&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;elm monolith/ui/src
-----------------------------------------------
Language    files    blank    comment      code
-----------------------------------------------
Elm          &lt;span class=&quot;token number&quot;&gt;1506&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;49759&lt;/span&gt;      &lt;span class=&quot;token number&quot;&gt;16535&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;211835&lt;/span&gt;
-----------------------------------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nothing much to add here. Moving on :)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cloc --include-ext&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;elm monolith/ui/tests
-----------------------------------------------
Language    files    blank    comment      code
-----------------------------------------------
Elm           &lt;span class=&quot;token number&quot;&gt;569&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;10275&lt;/span&gt;       &lt;span class=&quot;token number&quot;&gt;1309&lt;/span&gt;    &lt;span class=&quot;token number&quot;&gt;200586&lt;/span&gt;
-----------------------------------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, we write loads of tests. As much as the Elm compiler gives
you that wonderful confidence while refactoring, we still want to make sure
that our code is working as intended. We will talk more in-depth about
testing later.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cloc --include-ext&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;elm monolith/ui/generated
-----------------------------------------------
Language    files    blank    comment      code
-----------------------------------------------
Elm           &lt;span class=&quot;token number&quot;&gt;129&lt;/span&gt;     &lt;span class=&quot;token number&quot;&gt;2428&lt;/span&gt;       &lt;span class=&quot;token number&quot;&gt;1728&lt;/span&gt;     &lt;span class=&quot;token number&quot;&gt;26399&lt;/span&gt;
-----------------------------------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We end up auto-generating a lot of Elm code: we do this for multiple
purposes, such as automatically generating types from graphql, or ensuring
that JSON payloads sent from Rails controllers match the definitions inside
our Elm decoders.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ cloc --include-ext&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;elm content-creation
-----------------------------------------------
Language    files    blank    comment      code
-----------------------------------------------
Elm            &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;     &lt;span class=&quot;token number&quot;&gt;3245&lt;/span&gt;       &lt;span class=&quot;token number&quot;&gt;1182&lt;/span&gt;     &lt;span class=&quot;token number&quot;&gt;13941&lt;/span&gt;
-----------------------------------------------&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At last, here’s a snapshot of Elm code in one of our Haskell services. I
won’t spend much time describing how that works in this post, let me know
if you are interested and I’ll write a follow-up. For now, let’s take a
deeper look at how we integrate with Rails.&lt;/p&gt;
&lt;h2 id=&quot;rails-conventions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#rails-conventions&quot; aria-label=&quot;rails conventions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Rails conventions&lt;/h2&gt;
&lt;p&gt;Following the Rails architecture, each REST resource is managed by its
dedicated controller. Here is what happens when a teacher goes to manage
their classes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;they visit the &lt;code class=&quot;language-text&quot;&gt;/teach/classes&lt;/code&gt; URL in their browser&lt;/li&gt;
&lt;li&gt;that route is managed by the &lt;code class=&quot;language-text&quot;&gt;Teach::ClassesController&lt;/code&gt; controller&lt;/li&gt;
&lt;li&gt;that controller will fetch stuff from the database, clean it up and load a corresponding view, &lt;code class=&quot;language-text&quot;&gt;app/views/teach/classes/index.html.haml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That view looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haml&quot;&gt;&lt;pre class=&quot;language-haml&quot;&gt;&lt;code class=&quot;language-haml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token multiline-code&quot;&gt; content_for &lt;span class=&quot;token symbol&quot;&gt;:title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &quot;Manage Classes &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;/span&gt;NoRedInk&quot;

&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; content_for&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:javascript&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; javascript_include_tag &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;shake/Page/Teach/Classes/index.js&quot;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token code&quot;&gt; elm_mount&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;@elm_flags&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;teach-classes-elm&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What is that &lt;code class=&quot;language-text&quot;&gt;elm_mount&lt;/code&gt; helper? We define it to be like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;elm_mount&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;flags&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; prefix &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;elm&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  tag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;div&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; prefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;-flags&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token symbol&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;elm-flags&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token symbol&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; flags&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;to_json&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;
    tag&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;div&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; prefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;-host&apos;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In short, we need some conventions for the names of two DOM nodes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one that contains the flags that we pass from Rails to Elm: we use this
to pass data to the Elm application that needs to be available on boot&lt;/li&gt;
&lt;li&gt;one that will contain the actual Elm app when it’s mounted&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The javascript file that we include is the result of the compilation of the
Elm app. We use a build system called &lt;a href=&quot;https://shakebuild.com/&quot;&gt;Shake&lt;/a&gt; to
generate all our assets. The actual entry point looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; Elm &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;./Main.elm&quot;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; NriProgram &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Nri/Program.js&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; setupReadAloud &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ReadAloud/setup.js&quot;&lt;/span&gt;

NriProgram&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;domready&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; subscribe&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; send &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NriProgram&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mountPorts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    Elm&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Page&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Teach&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Classes&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Main&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;ui/src/Page/Teach/Classes/index.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&quot;teach-classes-elm&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;token function&quot;&gt;setupReadAloud&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; subscribe&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; send &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;NriProgram&lt;/code&gt; that you see here is a small wrapper around common
operations that we need to perform, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;passing an environment object to our apps so that we can have different
settings in test, development and production&lt;/li&gt;
&lt;li&gt;setting up some basic analytics and reporting&lt;/li&gt;
&lt;li&gt;grabbing the flags and the div where the Elm app will be mounted&lt;/li&gt;
&lt;li&gt;giving us the ability to easily set up ports using &lt;code class=&quot;language-text&quot;&gt;subscribe&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;send&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another interesting bit is the convention that we use to name our Elm
modules. Since the URL is going to be &lt;code class=&quot;language-text&quot;&gt;/teach/classes&lt;/code&gt;, the associated Elm
module is going to be &lt;code class=&quot;language-text&quot;&gt;Page.Teach.Classes.Main&lt;/code&gt;. Here are some other
examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Page.Admin.RelevantTerms.Main&lt;/code&gt; corresponds to &lt;code class=&quot;language-text&quot;&gt;/admin/relevant_terms&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Page.Learn.ChooseSourceMaterials.Main&lt;/code&gt; corresponds to &lt;code class=&quot;language-text&quot;&gt;/learn/choose_source_materials&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Page.Preferences.Main&lt;/code&gt; corresponds to &lt;code class=&quot;language-text&quot;&gt;/preferences&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Page.Teacher.Courses.Assignments.Main&lt;/code&gt; corresponds to &lt;code class=&quot;language-text&quot;&gt;/teach/courses/:id/assignments&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In total, we have over a hundred Elm apps that serve different Rails
controllers. They consist of a mixture of normal Elm applications and
single-page apps. By adapting the Rails motto of “convention over
configuration” we’re pretty confident we can scale this approach indefinitely.&lt;/p&gt;
&lt;h2 id=&quot;our-elm-programs&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#our-elm-programs&quot; aria-label=&quot;our elm programs permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Our Elm programs&lt;/h2&gt;
&lt;p&gt;At this point, you probably won’t be surprised to learn that we use a
custom wrapper as the entrypoint of our Elm programs. Here is how it looks
like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nri.Program.Program&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Nri.Program.program&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;moduleName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Page.Interests.Main&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;flagsDecoder&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; \_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;decode&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;perform&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;init&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; \_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Sub.none&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s compare it to &lt;code class=&quot;language-text&quot;&gt;Browser.element&lt;/code&gt; from &lt;code class=&quot;language-text&quot;&gt;elm/browser&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Browser.Program&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;flags&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Browser.element&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;init&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;init&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;subscriptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; \_ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Sub.none&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, the types are slightly different and we include a couple of
different fields in our version.&lt;/p&gt;
&lt;p&gt;What are the advantages of using a custom &lt;code class=&quot;language-text&quot;&gt;Nri.Program&lt;/code&gt;?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;reducing boilerplate&lt;/strong&gt;: for example, we can automatically handle decoding failures so that
we don’t have to worry about them on each individual page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;handling generic behaviours&lt;/strong&gt;: for example, we can automatically detect the user’s
input method to make our product more accessible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The differences don’t stop there. Let’s look at the type of the &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we take an additional &lt;code class=&quot;language-text&quot;&gt;Env&lt;/code&gt; argument. This record contains information
about the current release, the logged-in user and the environment where the
code is running. For example, if we detect that we are running in test
mode, there is no need to run fancy UI animations, thus we can disable
them. This in turn makes our tests faster and less flaky. Win-win!&lt;/p&gt;
&lt;p&gt;If you look at the record that we pass to &lt;code class=&quot;language-text&quot;&gt;Nri.Program.program&lt;/code&gt; you will notice
an additional &lt;code class=&quot;language-text&quot;&gt;perform&lt;/code&gt; field. Let’s look at the type signature:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;perform&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Effect&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Cmd&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is easier to understand if we look at the type signature of &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Effect&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The curious change is that a standard update function in Elm returns a
&lt;code class=&quot;language-text&quot;&gt;(Model, Cmd Msg)&lt;/code&gt; tuple, while ours returns &lt;code class=&quot;language-text&quot;&gt;(Model, Effect)&lt;/code&gt;. Why is
that? &lt;code class=&quot;language-text&quot;&gt;Cmd Msg&lt;/code&gt; is an opaque type that is meant to be passed as-is to the
Elm runtime. But in order to test that the correct side effect has been
emitted we need to be able to inspect it: so we define our own type and we
call it &lt;code class=&quot;language-text&quot;&gt;Effect&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then we can use the fantastic &lt;code class=&quot;language-text&quot;&gt;elm-program-test&lt;/code&gt; library (you can find it
&lt;a href=&quot;https://package.elm-lang.org/packages/avh4/elm-program-test/latest&quot;&gt;here&lt;/a&gt;)
to test our Elm programs. Meanwhile, in our normal application, we
can use the &lt;code class=&quot;language-text&quot;&gt;perform&lt;/code&gt; function to convert the &lt;code class=&quot;language-text&quot;&gt;Effect&lt;/code&gt; representation of a
side effect to its &lt;code class=&quot;language-text&quot;&gt;Cmd Msg&lt;/code&gt; counterpart.&lt;/p&gt;
&lt;p&gt;Similarly, we have another custom wrapper for single-page applications called
&lt;code class=&quot;language-text&quot;&gt;Nri.Spa.Program&lt;/code&gt; which mostly wraps &lt;code class=&quot;language-text&quot;&gt;Browser.application&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The general lesson here is that just because Elm provides an &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt;
function with the shape &lt;code class=&quot;language-text&quot;&gt;msg -&gt; model -&gt; (model, Cmd msg)&lt;/code&gt; your version
&lt;strong&gt;doesn’t need to&lt;/strong&gt;. You might need more arguments, or different types, or
more return values. As long as you convert the result of your function to
match the API of &lt;code class=&quot;language-text&quot;&gt;Browser.element&lt;/code&gt; you can customize your API as much as
you want.&lt;/p&gt;
&lt;h2 id=&quot;how-we-write-elm-files&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-we-write-elm-files&quot; aria-label=&quot;how we write elm files permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How we write Elm files&lt;/h2&gt;
&lt;p&gt;We don’t believe in the mantra:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Prefer small files&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here is a little snapshot of some large files in our codebase:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2251&lt;/span&gt; src/Page/Learn/GuidedDrafts/Main.elm
&lt;span class=&quot;token number&quot;&gt;1773&lt;/span&gt; src/Page/Curriculum/BrowseAndAssignLayout.elm
&lt;span class=&quot;token number&quot;&gt;1725&lt;/span&gt; src/Page/Teach/Classes/Page/Classes/Explore.elm
&lt;span class=&quot;token number&quot;&gt;1691&lt;/span&gt; src/Page/Teach/Assignment/Form/GuidedDraft/Customize.elm
&lt;span class=&quot;token number&quot;&gt;1524&lt;/span&gt; src/Page/Teach/Courses/PeerReviews/Progress.elm
&lt;span class=&quot;token number&quot;&gt;1280&lt;/span&gt; src/Page/Admin/Alignments/Main.elm
&lt;span class=&quot;token number&quot;&gt;1188&lt;/span&gt; src/Page/Learn/Home/Main.elm
&lt;span class=&quot;token number&quot;&gt;1184&lt;/span&gt; src/Page/Teach/Assignment/Form/Model.elm
&lt;span class=&quot;token number&quot;&gt;1136&lt;/span&gt; src/Page/Preview/PeerReview/Main.elm&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As Evan Czaplicki explains in &lt;a href=&quot;https://www.youtube.com/watch/XpDsk374LDE&quot;&gt;this
talk&lt;/a&gt;, larger files in Elm are
not a problem. We tend to delineate the different sections related to the
model, update and view functions with comments. Then we extract functions
around their data structures, rather than their perceived role.&lt;/p&gt;
&lt;p&gt;Another point I want to emphasize is that in Elm you don’t have to get
everything right from the start. Choose the simplest architecture that
works. If you need to change it later, the compiler will assist you every
step of the way. Specifically for this sort of mechanical changes, the
chance of introducing bugs is very close to zero. If it compiles, it works.&lt;/p&gt;
&lt;p&gt;We regularly merge refactors in the thousands of lines that don’t introduce
a single regression to the product. There is really nothing to be afraid
of! 🍧&lt;/p&gt;
&lt;h2 id=&quot;nesting-the-elm-architecture&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nesting-the-elm-architecture&quot; aria-label=&quot;nesting the elm architecture permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nesting the Elm Architecture&lt;/h2&gt;
&lt;p&gt;When we need to combine multiple Elm applications, we nest them under one
another. So for example if we have a modal in a page with its own state and
messages, we will do this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Modal.Model&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ModalMsg&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Modal.Msg&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Effect&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;ModalMsg&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modalMsg&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newModal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modalEffect&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;Modal.update&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modalMsg&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;modal&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newModal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ModalEffect&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modalEffect&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Modal.view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;modal&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.map&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ModalMsg&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Hello there&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s break this down.&lt;/p&gt;
&lt;p&gt;We have a top-level &lt;code class=&quot;language-text&quot;&gt;Msg&lt;/code&gt; type that describes the behaviour of the
top-level application. Its only variant is a &lt;code class=&quot;language-text&quot;&gt;ModalMsg Modal.Msg&lt;/code&gt; which
wraps the message type of the modal.&lt;/p&gt;
&lt;p&gt;When we receive a &lt;code class=&quot;language-text&quot;&gt;ModalMsg&lt;/code&gt; we pattern match to extract the inner message
and we run it against the modal state stored in the model through
&lt;code class=&quot;language-text&quot;&gt;Modal.update&lt;/code&gt;. Then we replace the modal with the updated version and do
something with the side effect.&lt;/p&gt;
&lt;p&gt;Something else to note is that we need to use &lt;code class=&quot;language-text&quot;&gt;Html.map&lt;/code&gt; to wrap the
&lt;code class=&quot;language-text&quot;&gt;Modal.view&lt;/code&gt; function. In this way, we ensure that all the messages that are
emitted are wrapped with the &lt;code class=&quot;language-text&quot;&gt;ModalMsg&lt;/code&gt; message constructor.&lt;/p&gt;
&lt;p&gt;This is how we build big apps in Elm. That’s the secret sauce. By applying
this concept repeatedly you can scale your Elm apps as much as you want.
Here is the actual &lt;code class=&quot;language-text&quot;&gt;Msg&lt;/code&gt; type of our &lt;code class=&quot;language-text&quot;&gt;Teach.Classes.Main&lt;/code&gt; module:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ChangePage&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Route&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- Nested TEA&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;TimedAlerts&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Alert.Msg&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ClassesMsg&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Classes.Msg&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ModalMsg&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Modal.Msg&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EditClassMsg&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EditClass.Msg&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- HTTP responses&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ReceiveClasses&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Class.RedirectToClass&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;WebData&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;activeClasses&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Class.Class&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;archivedClassCount&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ReceiveArchivedClasses&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;WebData&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Archived.Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- DOM focus&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Focus&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Focused&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Result&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Dom.Error&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;-- User actions&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;OpenModal&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Modal.Kind&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CloseModal&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;SetModalKind&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Modal.Kind&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ModalError&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Http.Error&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;AddStudent&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Modal.CreateStudentAccountsManuallyModel&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Archived&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Unarchived&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ToggleTooltip&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;when-to-nest-tea-modules&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#when-to-nest-tea-modules&quot; aria-label=&quot;when to nest tea modules permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;When to nest TEA modules&lt;/h2&gt;
&lt;p&gt;If you looked at the section above and you thought “welp, that looks like a
lot of work”, I hear you. As a matter of fact, you don’t need to do the
whole nesting dance every time we want to reuse a module. In fact, most of
the UI components that we use don’t have their own state, so they don’t
need even need an &lt;code class=&quot;language-text&quot;&gt;update&lt;/code&gt; function. Let’s look at how we use a button:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Nri.Ui.Button.V10 &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Button&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Env&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Button.link&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Edit&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Button.css&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Css.marginBottom&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;Css.px&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Button.onClick&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EditAssignment&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Button.icon&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;UiIcon.calendar&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Button.small&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It seems obvious, but if there is no state, then there is no need to do
extra work.&lt;/p&gt;
&lt;p&gt;If you are curious about how we structure our UI components, you can take a
gander at &lt;a href=&quot;https://github.com/NoRedInk/noredink-ui&quot;&gt;noredink-ui&lt;/a&gt; (check out
the preview &lt;a href=&quot;https://noredink-ui.netlify.app/&quot;&gt;here&lt;/a&gt;). We’re always
including simple examples for each UI component so that they act as the
best documentation possible
(&lt;a href=&quot;https://noredink-ui.netlify.app/#/doodad/Switch&quot;&gt;component&lt;/a&gt; /
&lt;a href=&quot;https://github.com/NoRedInk/noredink-ui/blob/master/styleguide-app/Examples/Switch.elm&quot;&gt;example&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;If you feel that it is too cumbersome to nest TEA applications, it may be
because &lt;em&gt;it just is&lt;/em&gt;. If you choose it as your default approach to scale
Elm code, you will find yourself constantly wrapping and unwrapping
messages for little or no benefit. I would recommend reaching for it as a
last resort, like using a rocket launcher to plant daffodils in your
garden: it works, but it’s a bit heavy-handed.&lt;/p&gt;
&lt;p&gt;Instead you might find some abstractions which don’t require another model
and another set of update messages. You can do lots with a view function
that takes a config record and an extensible record:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;viewSidebar&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;onClose&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sidebarItems&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;SidebarItem&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As mentioned above, choose the simplest solution that works. Later you can
refactor and make it feel good. You can watch &lt;a href=&quot;https://www.youtube.com/watch?v=DoA4Txr4GUs&quot;&gt;this
talk&lt;/a&gt; by Richard Feldman if you want
to learn more.&lt;/p&gt;
&lt;p&gt;A good point to reiterate is that, when writing Elm, you don’t have to get
everything right from the start. The compiler gives you an unprecedented
level of confidence when refactoring code. So go out there and make
mistakes, then fix them, then keep going.&lt;/p&gt;
&lt;h2 id=&quot;interacting-with-javascript&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#interacting-with-javascript&quot; aria-label=&quot;interacting with javascript permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Interacting with JavaScript&lt;/h2&gt;
&lt;p&gt;We mainly use &lt;a href=&quot;https://guide.elm-lang.org/interop/ports.html&quot;&gt;ports&lt;/a&gt; to
interact with JavaScript code. We have two simple rules for ports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All ports &lt;strong&gt;must&lt;/strong&gt; return values as &lt;code class=&quot;language-text&quot;&gt;Json.Value&lt;/code&gt;. If a &lt;code class=&quot;language-text&quot;&gt;Int -&gt; Cmd msg&lt;/code&gt;
port receives a float instead, it will cause a crash. This is one of the
simplest ways to introduce runtime errors in your application. By
treating all values as JSON blobs, we must decode them and deal with the
eventual decoding failure. Repeat with me, ports need JSON values.&lt;/li&gt;
&lt;li&gt;All port functions &lt;strong&gt;must&lt;/strong&gt; be documented in the Elm module. We don’t want to
go hunting in JavaScriptLand how a port is being used. A couple of lines
explaining what the port triggers can go a long way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In cases where ports are not enough, we use &lt;a href=&quot;https://guide.elm-lang.org/interop/custom_elements.html&quot;&gt;custom
elements&lt;/a&gt;. You
might want to do this for many reasons, such as reusing &lt;a href=&quot;https://github.com/cultureamp/react-elm-components&quot;&gt;existing React
components&lt;/a&gt; inside your
Elm application. In our case, we have integrated rich text editing using a
custom element that wraps &lt;a href=&quot;https://quilljs.com/&quot;&gt;quilljs&lt;/a&gt;. If you’re
interested in learning more about integrating custom elements in Elm, I
recommend watching &lt;a href=&quot;https://www.youtube.com/watch?v=tyFe9Pw6TVE&quot;&gt;this great talk&lt;/a&gt;
by Luke Westby.&lt;/p&gt;
&lt;h2 id=&quot;testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#testing&quot; aria-label=&quot;testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Testing&lt;/h2&gt;
&lt;p&gt;We write tests for our Elm code at four different layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unit tests&lt;/strong&gt;: these are pure tests around data structures. Create a piece
of data, run a function on it and assert some results.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;View tests&lt;/strong&gt;: here we construct a model, pass it to the view
function and write assertions against the result using &lt;code class=&quot;language-text&quot;&gt;elm-explorations/test&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration tests&lt;/strong&gt;: here we load up an auto-generated JSON file
(using &lt;code class=&quot;language-text&quot;&gt;rails_edge_test&lt;/code&gt;, find it &lt;a href=&quot;https://github.com/NoRedInk/rails_edge_test&quot;&gt;here&lt;/a&gt;), pass it to
the &lt;code class=&quot;language-text&quot;&gt;elm-program-test&lt;/code&gt; program, interact with the elements on the page,
and assert side effects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Acceptance tests&lt;/strong&gt;: we write these in Capybara as happy-path tests.
They are extremely useful to test JavaScript interop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I can recommend &lt;a href=&quot;https://www.youtube.com/watch?v=rIxCwPPA-D8&quot;&gt;this excellent
talk&lt;/a&gt; by Tessa Kelly if you
want to learn how to write testable Elm.&lt;/p&gt;
&lt;h2 id=&quot;tooling&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tooling&quot; aria-label=&quot;tooling permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Tooling&lt;/h2&gt;
&lt;p&gt;Here’s a selection of tools that we use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/avh4/elm-format&quot;&gt;elm-format&lt;/a&gt;, the Holy Grail of code
formatters. I love repeating “garbage in, code out”. In this
case, it happens to be beautifully formatted, while respecting your preference
in terms of whitespace, and applying tiny cleanups of your code on the
fly. What’s not to like?&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rtfeldman/elm-css&quot;&gt;elm-css&lt;/a&gt;, so that our CSS is
typed. We use it so much that the &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt; function in our &lt;code class=&quot;language-text&quot;&gt;Nri.Program&lt;/code&gt;
returns a &lt;code class=&quot;language-text&quot;&gt;Html.Styled.Html msg&lt;/code&gt; by default.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/tesk9/accessible-html&quot;&gt;accessible-html&lt;/a&gt;, or how to
ensure that accessibility is a first-class citizen in your app. I think
that this library is also a great case study on how to create a light
wrapper around another library.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jfmengels/elm-review&quot;&gt;elm-review&lt;/a&gt;, a must-have
addition to any Elm project. It will detect unused variables, unused
variants, unused modules, and much much more. Use it!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/NoRedInk/elm-json-decode-pipeline&quot;&gt;elm-json-decode-pipeline&lt;/a&gt;,
another approach at writing JSON decoders. I love how easy it is to read
and modify decoders written in this style.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s all for today, and if this sort of work interests you do check out &lt;a href=&quot;https://www.noredink.com/jobs&quot;&gt;this
page&lt;/a&gt;. Thanks for reading 👋&lt;/p&gt;
&lt;p&gt;&lt;em&gt;My eternal gratitude to the wonderful folks that have read through the drafts of
this post: &lt;a href=&quot;https://twitter.com/juanedi&quot;&gt;@juanedi&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/brianhicks&quot;&gt;@brianhicks&lt;/a&gt;,
&lt;a href=&quot;https://twitter.com/rtfeldman&quot;&gt;@rtfeldman&lt;/a&gt;, and
&lt;a href=&quot;https://twitter.com/michaelglass&quot;&gt;@michaelglass&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[There and back again]]></title><description><![CDATA[When writing Elm, it’s very common to use custom
types to structure
your data. Let’s say we want to describe the flashy suits of the Power…]]></description><link>https://juliu.is/there-and-back-again/</link><guid isPermaLink="false">https://juliu.is/there-and-back-again/</guid><pubDate>Fri, 26 Mar 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When writing Elm, it’s very common to use &lt;a href=&quot;https://guide.elm-lang.org/types/custom_types.html&quot;&gt;custom
types&lt;/a&gt; to structure
your data. Let’s say we want to describe the flashy suits of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Power_Rangers&quot;&gt;Power
Rangers&lt;/a&gt;, as featured in the
1975 classic &lt;a href=&quot;https://en.wikipedia.org/wiki/Himitsu_Sentai_Gorenger&quot;&gt;Himitsu Sentai
Gorenger&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This looks great, so we decide to go to the next level. We’re going to
build a fully-fledged Elm application to choose our favourite Power Ranger
suit color. We start with a simple model:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;chosenSuit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We then define an initial state of the model, where no suit has been chosen:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;initialModel&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;initialModel&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;chosenSuit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can write a view function to display something:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Html &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Html.Attributes &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Attrs&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose your Power Ranger Suit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is unfortunate. We have to use strings and pass them to &lt;code class=&quot;language-text&quot;&gt;Attrs.value&lt;/code&gt;
and to &lt;code class=&quot;language-text&quot;&gt;Html.text&lt;/code&gt;, which means we can’t use the beautiful custom type we
wrote above. To be able to do that, we have to define a &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And use it to dry up the view:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose your Power Ranger Suit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can play around with this &lt;a href=&quot;https://ellie-app.com/cDq7YCwvfpBa1&quot;&gt;Ellie app&lt;/a&gt;
to see how that looks like.&lt;/p&gt;
&lt;p&gt;If you’re a bit more experienced with Elm, you will notice that you can
choose an option in the select, but that won’t update the &lt;code class=&quot;language-text&quot;&gt;Model&lt;/code&gt;.
Let’s prove that assumption by changing the view to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose your Power Ranger Suit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;chosenSuit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;No suit was chosen.&quot;&lt;/span&gt;

                &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Your choice: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you &lt;a href=&quot;https://ellie-app.com/cK5MMdrG8LYa1&quot;&gt;can see&lt;/a&gt;, no matter how you
change the view, the value won’t be updated. This happens because we
haven’t defined a &lt;code class=&quot;language-text&quot;&gt;onInput&lt;/code&gt; event on the select :(&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Html.Events &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Events&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.h2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose your Power Ranger Suit&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.select&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Events.onInput&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ChooseSuit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Choose&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.p&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;chosenSuit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;No suit was chosen.&quot;&lt;/span&gt;

                &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Your choice: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ChooseSuit&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;update&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;ChooseSuit&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;chosenSuit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s that &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt; function? Here it is:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;

        _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this &lt;a href=&quot;https://ellie-app.com/cDqjV9LLFX6a1&quot;&gt;Ellie app&lt;/a&gt;, we can see
that everything is working nicely :)&lt;/p&gt;
&lt;h2 id=&quot;an-interesting-pair&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#an-interesting-pair&quot; aria-label=&quot;an interesting pair permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;An interesting pair&lt;/h2&gt;
&lt;p&gt;We notice a terrible bug in our application: we forgot about the Pink
Power Ranger! Let’s fix that by adding a new variant:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we save the file, we’ll notice the Elm compiler being helpful as ever:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;This&lt;/span&gt; `&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt;` &lt;span class=&quot;token hvariable&quot;&gt;does&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;have&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;branches&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;possibilities&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;token number&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;        &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;            &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;        &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;            &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;        &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;            &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;29&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;        &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt;            &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Missing&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;possibilities&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cool, we need to add the missing case in &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt;

        &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;Pink&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we save now the app compiles. But if we try using the app, we can see
that there is no &lt;code class=&quot;language-text&quot;&gt;Pink&lt;/code&gt; option :( It turns out we forgot to add the option
inside the &lt;code class=&quot;language-text&quot;&gt;selectOptions&lt;/code&gt; function. Maybe we can also extract the list of
suits into another function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;selectOptions&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;Html.option&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attrs.value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Try the &lt;a href=&quot;https://ellie-app.com/cDqsN2T5bSma1&quot;&gt;app&lt;/a&gt; now. This is what
happens when you choose ‘Pink’ in the dropdown:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/669b5dfa2cd09f93a7ae9ab0c79e9428/37523/pink-sadness.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 39.24050632911392%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAAA5ElEQVR42q1QuYqFQBD0///FRMTkBR4I3lfghYiCmBp4IJ61dIOwu7DwFl5BUcx0d01PCfgg7vuGkGUZFEWB7/twHAdt2yJNU1iWhTzPIcsywjBEFEVIkgSSJHGNeuM45rnX6wXbttlU6Puei6ZpMouigOd50HWdzcmIDGmwqioYhgFN0yCKIoIgQF3XUFWVzdnwOA5e9WNfpi1c18U4jui6DsuycPG6Lm4g/c7zPJm/70h5w2masK4r5nlm3baNdd93bnxefvjX+YFAGVA2ZVmiaRpWypEyGYbhh8E7EN7J5T/4ArQmYEqiAV5QAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;pink sadness&quot;
        title=&quot;&quot;
        src=&quot;/static/669b5dfa2cd09f93a7ae9ab0c79e9428/f058b/pink-sadness.png&quot;
        srcset=&quot;/static/669b5dfa2cd09f93a7ae9ab0c79e9428/c26ae/pink-sadness.png 158w,
/static/669b5dfa2cd09f93a7ae9ab0c79e9428/6bdcf/pink-sadness.png 315w,
/static/669b5dfa2cd09f93a7ae9ab0c79e9428/f058b/pink-sadness.png 630w,
/static/669b5dfa2cd09f93a7ae9ab0c79e9428/37523/pink-sadness.png 720w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This makes me sad, since I love to repeat:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If it compiles, it works&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And in the last minute we already bumped into two cases where the code
compiles, but doesn’t work. As you probably guessed, the bug is hidden in
our &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Yellow&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;

        &lt;span class=&quot;token string&quot;&gt;&quot;Pink&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;

        _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is the key difference between the &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt; function and the
&lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt; function: &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt; takes a &lt;code class=&quot;language-text&quot;&gt;Suit&lt;/code&gt;, so the compiler can warn
us if we forget to consider one of the possible alternatives. In the case
of &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt;, the valid inputs are &lt;strong&gt;all possible strings&lt;/strong&gt;, so the
compiler can’t do much to warn us.&lt;/p&gt;
&lt;p&gt;But as humans, we can tell that these two functions are &lt;em&gt;really&lt;/em&gt; similar.
Is there nothing we can do to express it in code? Let’s go for a little trip.&lt;/p&gt;
&lt;h2 id=&quot;a-trip-in-haskell-land&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-trip-in-haskell-land&quot; aria-label=&quot;a trip in haskell land permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A trip in Haskell Land&lt;/h2&gt;
&lt;p&gt;Let’s define the same type in Haskell:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order to implement the &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt; function we can derive the &lt;code class=&quot;language-text&quot;&gt;Show&lt;/code&gt;
typeclass, which will know how to convert our custom type to a string:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we take it for a spin:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;Green&quot;&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;Blue&quot;&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&quot;Pink&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let’s figure out a way to define the &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt; function. We can
start by defining an &lt;code class=&quot;language-text&quot;&gt;allSuits&lt;/code&gt; function. We will do so by deriving other
two typeclasses, named &lt;code class=&quot;language-text&quot;&gt;Enum&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Bounded&lt;/code&gt;. The first one tells the
compiler that our type is an enumeration of sequentially ordered types,
while the second specifies that our type has a minimum value and a maximum
value.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bounded&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;minBound&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;maxBound&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which results in:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Green&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Yellow&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Blue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Cool! Now we can write that &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;qualified&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Map &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Map&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;suitMap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Map&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;suitMap&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;Map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fromList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;lookup&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suitMap&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here it is working:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Red&quot;&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Red&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Pink&quot;&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pink&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Geronimo&quot;&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, in Haskell Land we were able to define the relationship
between &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt;. If we add a new variant to the &lt;code class=&quot;language-text&quot;&gt;Suit&lt;/code&gt;
type, it will be picked up and everything will work as intended. This
technique is described in more detail in the wonderful &lt;a href=&quot;https://kowainik.github.io/posts/haskell-mini-patterns#bidirectional-parsing&quot;&gt;Haskell
Mini-Patterns
Handbook&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;coming-back-home&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#coming-back-home&quot; aria-label=&quot;coming back home permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Coming back home&lt;/h2&gt;
&lt;p&gt;Is there a way to achieve something similar in Elm?&lt;/p&gt;
&lt;p&gt;Yes, there is! 🍨&lt;/p&gt;
&lt;p&gt;Truth be told, we can’t do &lt;em&gt;exactly&lt;/em&gt; what Haskell does, but we can &lt;em&gt;emulate&lt;/em&gt; Haskell’s behaviour by using a wonderful library called &lt;a href=&quot;https://package.elm-lang.org/packages/jfmengels/elm-review/latest/&quot;&gt;elm-review&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;elm-review&lt;/code&gt; analyzes your Elm code and reports patterns that violate
certain rules. We can use it to enforce additional guarantees on our
projects, such as removing unused functions, unused values, unused modules,
and unused dependencies. You can read more about it
&lt;a href=&quot;https://jfmengels.net/announcing-elm-review&quot;&gt;here&lt;/a&gt; and
&lt;a href=&quot;https://jfmengels.net/safe-dead-code-removal&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In our case, we can write a rule that detects functions named like
&lt;code class=&quot;language-text&quot;&gt;allSuits&lt;/code&gt; and tell it to warn us when we forget to include a type
constructor. I’ve shamefully stolen a &lt;a href=&quot;https://gist.github.com/jfmengels/e1fd40af3d0e7bde707c0241bf46920f&quot;&gt;gist&lt;/a&gt; from Jeroen Engels and pushed it
as an elm-review package
&lt;a href=&quot;https://github.com/Arkham/elm-review-no-missing-type-constructor&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you’d like to follow along you can pull &lt;a href=&quot;https://github.com/Arkham/elm-there-and-back-again&quot;&gt;this repo&lt;/a&gt; and then run:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ npx elm-review &lt;span class=&quot;token parameter variable&quot;&gt;--template&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  Arkham/elm-review-no-missing-type-constructor/example
✔ Fetching template information
-- ELM-REVIEW ERROR ------------------- src/Main.elm:46:1

NoMissingTypeConstructor: &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;allSuits&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; does not contain all
the &lt;span class=&quot;token builtin class-name&quot;&gt;type&lt;/span&gt; constructors &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;Suit&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token number&quot;&gt;45&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; allSuits &lt;span class=&quot;token builtin class-name&quot;&gt;:&lt;/span&gt; List Suit
&lt;span class=&quot;token number&quot;&gt;46&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; allSuits &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    ^^^^^^^^
&lt;span class=&quot;token number&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; Green, Yellow, Red, Blue &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

We &lt;span class=&quot;token function&quot;&gt;expect&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;allSuits&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt; to contain all the &lt;span class=&quot;token builtin class-name&quot;&gt;type&lt;/span&gt; constructors
&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;Suit&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;

In this case, you are missing the following constructors:
, Pink

I found &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; error &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; file.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;🎉 🎉 🎉&lt;/p&gt;
&lt;p&gt;Now we can implement a solution which is very similar to the Haskell one!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Dict &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Dict&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;suitDict&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Dict&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;suitDict&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Dict.fromList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;|&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;allSuits&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Suit&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;fromString&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Dict.get&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;suitDict&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now when we add a new variant of &lt;code class=&quot;language-text&quot;&gt;Suit&lt;/code&gt;, the Elm compiler will nudge us to
update &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt;, while elm-review will nudge us to add the missing
variant to &lt;code class=&quot;language-text&quot;&gt;allSuits&lt;/code&gt;, which in turn is going to make sure that &lt;code class=&quot;language-text&quot;&gt;toString&lt;/code&gt;
and &lt;code class=&quot;language-text&quot;&gt;fromString&lt;/code&gt; will never go out of sync. Here’s a link to the &lt;a href=&quot;https://ellie-app.com/cDrHpYTXsr9a1&quot;&gt;final
version&lt;/a&gt; of the code for you to
peruse.&lt;/p&gt;
&lt;p&gt;Thanks for reading! 👋&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A simple tmux config]]></title><description><![CDATA[I friggin’ love tmux. It makes my
day-to-day terminal experience so. much. better. Being
efficient in tmux means you don’t need tabs any…]]></description><link>https://juliu.is/a-simple-tmux/</link><guid isPermaLink="false">https://juliu.is/a-simple-tmux/</guid><pubDate>Mon, 22 Mar 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I friggin’ love &lt;a href=&quot;https://github.com/tmux/tmux&quot;&gt;tmux&lt;/a&gt;. It makes my
day-to-day terminal experience &lt;strong&gt;so&lt;/strong&gt;. &lt;strong&gt;much&lt;/strong&gt;. &lt;strong&gt;better&lt;/strong&gt;. Being
efficient in tmux means you don’t need tabs any longer. It means you can
update your terminal emulator while keeping your work intact. It means you
can sling panes and windows across your terminal as if you were the Last
Airbender. It’s that good.&lt;/p&gt;
&lt;p&gt;I thought I’d share a couple of tricks I’ve picked up over the years. I’d
heartily recommend reading and understanding each line of your configuration:
in this way, when things go wrong (and they will), you’ll be more likely to
have a hunch of the cause of the problem.&lt;/p&gt;
&lt;p&gt;Here’s a short demo:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/8d4a542e78605410e5ec2d11fe2377db/tmux.gif&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;mac-os-install&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mac-os-install&quot; aria-label=&quot;mac os install permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Mac OS install&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; tmux&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;tat&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tat&quot; aria-label=&quot;tat permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;tat&lt;/h2&gt;
&lt;p&gt;First of all I want you to add this function to your &lt;code class=&quot;language-text&quot;&gt;~/.bashrc&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;~/.zshrc&lt;/code&gt;
or whichever shell you’re using:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# tat: tmux attach&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function-name function&quot;&gt;tat&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token assign-left variable&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;basename&lt;/span&gt; `pwd` &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sed&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;s/\.//g&apos;&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; tmux &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;2&lt;/span&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;&amp;amp;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    tmux attach &lt;span class=&quot;token parameter variable&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; .envrc &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
    direnv &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; / tmux new-session &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
    tmux new-session &lt;span class=&quot;token parameter variable&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;fi&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;gets the name of the current directory and removes periods, which tmux
doesn’t like.&lt;/li&gt;
&lt;li&gt;if any session with the same name is open, it re-attaches to it.&lt;/li&gt;
&lt;li&gt;otherwise, it checks if an &lt;code class=&quot;language-text&quot;&gt;.envrc&lt;/code&gt; file is present and starts a new tmux
session using &lt;code class=&quot;language-text&quot;&gt;direnv exec&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;otherwise, starts a new tmux session with that name.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is what I do every time I start working on any project:
open the terminal, &lt;code class=&quot;language-text&quot;&gt;cd&lt;/code&gt; into the folder, then &lt;code class=&quot;language-text&quot;&gt;tat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now let’s take a look at the tmux configuration.&lt;/p&gt;
&lt;h2 id=&quot;general-configuration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#general-configuration&quot; aria-label=&quot;general configuration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;General configuration&lt;/h2&gt;
&lt;p&gt;Your config should live in &lt;code class=&quot;language-text&quot;&gt;~/.tmux.conf&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;mouse&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mouse&quot; aria-label=&quot;mouse permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Mouse&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; mouse on&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Welcome to the twenty-first century.&lt;/p&gt;
&lt;h3 id=&quot;command-history&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#command-history&quot; aria-label=&quot;command history permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Command history&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; history-limit &lt;span class=&quot;token number&quot;&gt;102400&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;Those who cannot remember the past are condemned to repeat it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;window-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#window-management&quot; aria-label=&quot;window management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Window management&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; base-index &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
setw &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; pane-base-index &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By default, tmux will number panes and windows starting from &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;. I find
indexing things from &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt; to be more ergonomic, especially when you want to
quickly switch between windows.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; renumber-windows on&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By default, after you delete a window tmux will remember the previous
index of the other windows. Why? I dunno, but this gets rid of it.&lt;/p&gt;
&lt;h3 id=&quot;keys-modes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#keys-modes&quot; aria-label=&quot;keys modes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Keys modes&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Use emacs keybindings in the status line&lt;/span&gt;
set-option &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; status-keys emacs

&lt;span class=&quot;token comment&quot;&gt;# Use vim keybindings in copy mode&lt;/span&gt;
setw &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; mode-keys &lt;span class=&quot;token function&quot;&gt;vi&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Fix ESC delay in vim&lt;/span&gt;
&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; escape-time &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even if you’re a hardcore vim user, you’ll want to use emacs keybinding in
the status line.&lt;/p&gt;
&lt;h2 id=&quot;key-bindings&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#key-bindings&quot; aria-label=&quot;key bindings permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Key Bindings&lt;/h2&gt;
&lt;h3 id=&quot;prefix&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prefix&quot; aria-label=&quot;prefix permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prefix&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;unbind C-b
&lt;span class=&quot;token builtin class-name&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; prefix C-a&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The prefix is the entry point to each command you’re going to use. I chose
&lt;code class=&quot;language-text&quot;&gt;Ctrl-a&lt;/code&gt; because it’s easier to press with my left hand.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;bind&lt;/span&gt; C-a send-prefix&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since we set &lt;code class=&quot;language-text&quot;&gt;Ctrl-a&lt;/code&gt; to be our prefix, it will be intercepted by tmux and
won’t be forwarded to any program. With this setting, we can press it twice
to send it through anyways.&lt;/p&gt;
&lt;h3 id=&quot;copy-mode&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#copy-mode&quot; aria-label=&quot;copy mode permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Copy mode&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;unbind-key &lt;span class=&quot;token parameter variable&quot;&gt;-T&lt;/span&gt; copy-mode-vi &lt;span class=&quot;token function&quot;&gt;v&lt;/span&gt;

bind-key &lt;span class=&quot;token parameter variable&quot;&gt;-T&lt;/span&gt; copy-mode-vi &lt;span class=&quot;token function&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  send-keys &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; begin-selection

bind-key &lt;span class=&quot;token parameter variable&quot;&gt;-T&lt;/span&gt; copy-mode-vi &lt;span class=&quot;token string&quot;&gt;&apos;C-v&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  send-keys &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; rectangle-toggle

bind-key &lt;span class=&quot;token parameter variable&quot;&gt;-T&lt;/span&gt; copy-mode-vi y &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  send-keys &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; copy-pipe-and-cancel &lt;span class=&quot;token string&quot;&gt;&quot;pbcopy&quot;&lt;/span&gt;

bind-key &lt;span class=&quot;token parameter variable&quot;&gt;-T&lt;/span&gt; copy-mode-vi MouseDragEnd1Pane &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;
  send-keys &lt;span class=&quot;token parameter variable&quot;&gt;-X&lt;/span&gt; copy-pipe-and-cancel &lt;span class=&quot;token string&quot;&gt;&quot;pbcopy&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In tmux, you can enter navigation mode by pressing &lt;code class=&quot;language-text&quot;&gt;Ctrl-a [&lt;/code&gt;. Once
you’re in that mode, you can navigate the buffer as if you were inside a
VIM buffer. Now you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;search for things with &lt;code class=&quot;language-text&quot;&gt;/&lt;/code&gt;; find next matches with &lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt; and previous
matches with &lt;code class=&quot;language-text&quot;&gt;N&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;start a visual selection with &lt;code class=&quot;language-text&quot;&gt;v&lt;/code&gt;; you can switch to rectangle mode with
&lt;code class=&quot;language-text&quot;&gt;Ctrl-v&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;copy the visual selection into your OS clipboard with &lt;code class=&quot;language-text&quot;&gt;y&lt;/code&gt;; this will
automatically cancel the selection. The same works by just highlighting
text with your mouse.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;quick-reload&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#quick-reload&quot; aria-label=&quot;quick reload permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Quick reload&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;bind&lt;/span&gt; r source-file ~/.tmux.conf &lt;span class=&quot;token punctuation&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; display &lt;span class=&quot;token string&quot;&gt;&quot;Config reloaded!&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A blessing when you’re testing out changes in your config.&lt;/p&gt;
&lt;h3 id=&quot;more-windows-management&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#more-windows-management&quot; aria-label=&quot;more windows management permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;More windows management&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;bind c new-window -c &apos;#{pane_current_path}&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Press &lt;code class=&quot;language-text&quot;&gt;Ctrl-a c&lt;/code&gt; to open a new window with the same path.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;bind &apos;\&apos; split-window -h -c &apos;#{pane_current_path}&apos;
bind - split-window -v -c &apos;#{pane_current_path}&apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Use &lt;code class=&quot;language-text&quot;&gt;Ctrl-a \&lt;/code&gt; to open a vertical split (it’s the same key with the
&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt; symbol). Use &lt;code class=&quot;language-text&quot;&gt;Ctrl-a -&lt;/code&gt; to open a horizontal split.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;bind&lt;/span&gt; b break-pane &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Press &lt;code class=&quot;language-text&quot;&gt;Ctrl-a b&lt;/code&gt; to break the current pane into a new window.&lt;/p&gt;
&lt;p&gt;Another shortcut I use all the time is &lt;code class=&quot;language-text&quot;&gt;Ctrl-a z&lt;/code&gt; to expand the current
pane full-screen. Press it again to return to your previous pane
configuration.&lt;/p&gt;
&lt;h3 id=&quot;vim-integration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#vim-integration&quot; aria-label=&quot;vim integration permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Vim integration&lt;/h3&gt;
&lt;p&gt;First of all, install
&lt;a href=&quot;https://github.com/christoomey/vim-tmux-navigator&quot;&gt;vim-tmux-navigator&lt;/a&gt; and
add these lines to your &lt;code class=&quot;language-text&quot;&gt;~/.vimrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;vim&quot;&gt;&lt;pre class=&quot;language-vim&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;nnoremap &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;J&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;W&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;j&lt;/span&gt;
nnoremap &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;K&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;W&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;k&lt;/span&gt;
nnoremap &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;H&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;W&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;h&lt;/span&gt;
nnoremap &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;L&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;C&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;W&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;l&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These will allow us to switch between Vim splits by just pressing
&lt;code class=&quot;language-text&quot;&gt;Ctrl-j&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;Ctrl-w j&lt;/code&gt;. Then add this to your
&lt;code class=&quot;language-text&quot;&gt;~/.tmux.conf&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;is_vim=&quot;ps -o state= -o comm= -t &apos;#{pane_tty}&apos; \
    | grep -iqE &apos;^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$&apos;&quot;
bind-key -n &apos;C-h&apos; if-shell &quot;$is_vim&quot; &apos;send-keys C-h&apos;  &apos;select-pane -L&apos;
bind-key -n &apos;C-j&apos; if-shell &quot;$is_vim&quot; &apos;send-keys C-j&apos;  &apos;select-pane -D&apos;
bind-key -n &apos;C-k&apos; if-shell &quot;$is_vim&quot; &apos;send-keys C-k&apos;  &apos;select-pane -U&apos;
bind-key -n &apos;C-l&apos; if-shell &quot;$is_vim&quot; &apos;send-keys C-l&apos;  &apos;select-pane -R&apos;
tmux_version=&apos;$(tmux -V | sed -En &quot;s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p&quot;)&apos;
if-shell -b &apos;[ &quot;$(echo &quot;$tmux_version &lt; 3.0&quot; | bc)&quot; = 1 ]&apos; \
    &quot;bind-key -n &apos;C-\\&apos; if-shell \&quot;$is_vim\&quot; &apos;send-keys C-\\&apos;  &apos;select-pane -l&apos;&quot;
if-shell -b &apos;[ &quot;$(echo &quot;$tmux_version &gt;= 3.0&quot; | bc)&quot; = 1 ]&apos; \
    &quot;bind-key -n &apos;C-\\&apos; if-shell \&quot;$is_vim\&quot; &apos;send-keys C-\\\\&apos;  &apos;select-pane -l&apos;&quot;

bind-key -T copy-mode-vi &apos;C-h&apos; select-pane -L
bind-key -T copy-mode-vi &apos;C-j&apos; select-pane -D
bind-key -T copy-mode-vi &apos;C-k&apos; select-pane -U
bind-key -T copy-mode-vi &apos;C-l&apos; select-pane -R
bind-key -T copy-mode-vi &apos;C-\&apos; select-pane -l&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now you will be able to seamlessly navigate between Vim splits and tmux
panes using &lt;code class=&quot;language-text&quot;&gt;Ctrl-h&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Ctrl-j&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Ctrl-k&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;Ctrl-l&lt;/code&gt;. You can switch
between the last two panes by repeatedly pressing &lt;code class=&quot;language-text&quot;&gt;Ctrl-\&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;cool-status-bar&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cool-status-bar&quot; aria-label=&quot;cool status bar permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Cool status bar&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;set-option -g status-justify left
set-option -g status-left &apos;#[bg=colour72] #[bg=colour237] #[bg=colour236] #[bg=colour235]#[fg=colour185] #S #[bg=colour236] &apos;
set-option -g status-left-length 16
set-option -g status-bg colour237
set-option -g status-right &apos;#[bg=colour236] #[bg=colour235]#[fg=colour185] %a %R #[bg=colour236]#[fg=colour3] #[bg=colour237] #[bg=colour72] #[]&apos;
set-option -g status-interval 60

set-option -g pane-active-border-style fg=colour246
set-option -g pane-border-style fg=colour238

set-window-option -g window-status-format &apos;#[bg=colour238]#[fg=colour107] #I #[bg=colour239]#[fg=colour110] #[bg=colour240]#W#[bg=colour239]#[fg=colour195]#F#[bg=colour238] &apos;
set-window-option -g window-status-current-format &apos;#[bg=colour236]#[fg=colour215] #I #[bg=colour235]#[fg=colour167] #[bg=colour234]#W#[bg=colour235]#[fg=colour195]#F#[bg=colour236] &apos;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here’s a preview:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/92d5b284287e2f95b87834601cbc734e/3c2d4/status-bar.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.82278481012659%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAACGElEQVR42o2SSU8bQRBG5xiWCAFisWfxLL3M3rNjbANBXEI25ZJ/kVMO/P0XeXAcQCjk8FRdqupPX1e1Fce3RCph6mVMbY3tprheyswvmEwVh0cep2cRxycBe+8nf9k/Z2//hN29I3Z2D3m3c8D+gY3lhTXGKIRw0NEZfmgz823CwMW2J0xtG89zmc0cPM/e4DzB3dRdzs59rFAPmCaj7TI+DBFtpTFlQmEyahOzaAVFplEqRuuX6C1xrHE8jRXpHtMktG3CVRdw3YdcDwF9q7jqQ3oTkqcCKeU/0UoysSMsEfdUXUbXJ9wOATd9yNBKFr2gKyPCSCGkQqn1RTWi1HPkpj7zNZZMBpohZz5PuJ2HLC81q7lkXkcksdw2/4mPvBSUaK2YTEOsKO7Jy4Q815S5Gs+NkWSxeEVMvcq6rrXEtgVWoFpMJihTMTpSUiKE+m+xp0/2Z3ot2JAkiotGcDcPqAqxaZRvCj13qHBciTUTDVrFpHFEnQUIIRAbl0KqN7crx16BECG2I7B8bejWm20SVvOKocvJUz2OocjkdujjhkdH+hH9GNf/MU0z6rrGcRVWfSv58fOYb98v+Xz/keXygrrKacqYuogpi4zKFJRFSp4lVGU+5nVVUJmcoWv4+uWeh4dfXFzeYDnpEpVWhConUBlFe43p7/AjM5KYJd3qE4lZIbM5qlggi8U2hkmLr3JmOuc0avgNH+58X7I4qOIAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;status bar&quot;
        title=&quot;&quot;
        src=&quot;/static/92d5b284287e2f95b87834601cbc734e/f058b/status-bar.png&quot;
        srcset=&quot;/static/92d5b284287e2f95b87834601cbc734e/c26ae/status-bar.png 158w,
/static/92d5b284287e2f95b87834601cbc734e/6bdcf/status-bar.png 315w,
/static/92d5b284287e2f95b87834601cbc734e/f058b/status-bar.png 630w,
/static/92d5b284287e2f95b87834601cbc734e/40601/status-bar.png 945w,
/static/92d5b284287e2f95b87834601cbc734e/78612/status-bar.png 1260w,
/static/92d5b284287e2f95b87834601cbc734e/3c2d4/status-bar.png 2092w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;fin&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#fin&quot; aria-label=&quot;fin permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fin&lt;/h2&gt;
&lt;p&gt;If you’d like, you can get a copy of the whole config &lt;a href=&quot;https://github.com/Arkham/dotfiles.nix/blob/master/tmux.conf&quot;&gt;here&lt;/a&gt;. If you don’t feel like maintaining this configuration yourself you can try out &lt;a href=&quot;https://github.com/tmux-plugins/tmux-sensible&quot;&gt;tmux-sensible&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Feel free to reach out on Twitter for help. That’s all, thanks for reading! 🌊&lt;/p&gt;</content:encoded></item><item><title><![CDATA[z-index by examples]]></title><description><![CDATA[I’ve been writing software “for a living” for more than ten years. I’m
afraid I have to admit that, for more than ten years, I’ve been using…]]></description><link>https://juliu.is/z-index-by-examples/</link><guid isPermaLink="false">https://juliu.is/z-index-by-examples/</guid><pubDate>Mon, 01 Feb 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been writing software “for a living” for more than ten years. I’m
afraid I have to admit that, for more than ten years, I’ve been using
&lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; without really understanding it.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; is a CSS property that is used to position elements above or
below one another. It’s your weapon of choice if you have two overlapping
elements and you want to decide which one goes on top. It’s quite useful
for modals, tooltips, banners, etc. You can set it to an integer and a
larger value will generally result in the element being rendered on top of
the rest.&lt;/p&gt;
&lt;p&gt;That’s pretty much all I knew about it.&lt;/p&gt;
&lt;p&gt;Usually, this is great in software: &lt;em&gt;“Learn enough to be dangerous”&lt;/em&gt; they
say. But invariably I would find myself fighting with &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; and
spending hours trying to understand what is wrong with Life, the Universe,
and Everything.&lt;/p&gt;
&lt;p&gt;I’m pretty sure it’s not just me. It’s common to bump into CSS like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;z-index: 99999&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which is pretty much the equivalent of the developer saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;this is too wild, byeee&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, let’s tackle this beast with some examples.&lt;/p&gt;
&lt;h2 id=&quot;the-setup&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-setup&quot; aria-label=&quot;the setup permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The setup&lt;/h2&gt;
&lt;p&gt;I’ve created a &lt;a href=&quot;https://z-index.juliu.is&quot;&gt;little app&lt;/a&gt; to make things easy. It looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/0934b66d1336f77082fefca1db90c94f/f02b9/preview.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAADtklEQVR42o2UW0ybZRjHufXChG0WWqDr95Vl5dzhgA0Z2EIWGfREsdIjZZoopQywgsAU4zGQKIchslES5riAOw7RKFs0WSYbG+gVgQsJ4B03XhAIhoDlZ/oRypZe4Jv88uT5kveXPO/3f98YlUpFfHz8C8jlcmQyGYIgUFxcjMVSQVn5NSxWExmZaSQmKVAJSs6qklAJZ1Gr1YiiKBGj1Wrxer1YrVZMJhNmszlCuA9/1+v1ZGgucjHjCtnpr5Gdli/xanoBGZpsBFGQpGFiqqqqOGndfzCD+XITAetd6o2D3DDexm8cJGC5S2VRI0pVAsnq5EOhw+E4Ufjot4cY8vw0WoLUlvfhK79FbVkfDaYhLIX+F4U5OTkEAgH8fn8UdXV1NDY2UWE1YytqpsE8hM9wizpDPz5DHw3mIJbCepSqxGNhSUkJU1NTjI+PRzE2NsbkxCQffXwTa8H7NJmGqC0doLZ0kPfeGKDJMIy1oBZlUtyx0O12nzjys/k5jLl+/JUj1Dm6aHB9yQ3XF/jsd7h2tQ1lWibq5HOow3/ZYDCwvLzM0tJSFIuLi6yv/8XQ8BC2Sw2U+X6gcaaUntnzdM+ep/ROJ3EdCyQGxhA1aagF1WFsampqsFgsUlSO6hHh2Oj0erTqLFLsnxN4VErnQhKdfyjJD35N7KeLJLZNImrSD4U2m41QKMT+/j57e3tSPWJ3d1ca+eeZ+8hiXyLB2sRnDy08fZbKk/lMbk+8i/jVYxQtkyQfCZ1O54ln+GTuKYpTLyOruIn7+yAs5MLv+fwz9zqZ3zzgVPOPCJpUxLAwLy+Pjo4OWltbaW5upqWlJUK4b29vx+FyIyjOcNrYRtm3kzB7CR7n8/evV7nc9RPCBxNkpWVyThSI0el0UkRGRkYIBoMMDw9HCPejo6O0fNiKShbLmapPMHb9ArWVHNTZ2fc5Waup50+Pn3XrW1gys4hxuVwnjjw/v4D8ldPE5xZjLb8OtmpCNq9UqXKC3QWuGpwXsokJPwBra2usrq5GsbKywsbGBqP37pGoSEChTMSWqgGXlwOHRyLkqOZfRzU4qrFrLxzGJnyfn49KVGx0OtSCQLwgYNNmg9NLyO7h4DkiwsrKSnZ2dtje3mZra0uqR2xubnJwcMD09DQJcjkKUeTNLK20ea/Kzb7dEyEi/D+xmZ2dRR4Xh1wUpU143gH39RfxvI07fIYFBQX09vbS09MTRXd3NwMDA9LLo0xKQimKXElJ5bsiPf2FOvqLjhko0lOUksp/lAWyvGBXwVsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;preview&quot;
        title=&quot;&quot;
        src=&quot;/static/0934b66d1336f77082fefca1db90c94f/f058b/preview.png&quot;
        srcset=&quot;/static/0934b66d1336f77082fefca1db90c94f/c26ae/preview.png 158w,
/static/0934b66d1336f77082fefca1db90c94f/6bdcf/preview.png 315w,
/static/0934b66d1336f77082fefca1db90c94f/f058b/preview.png 630w,
/static/0934b66d1336f77082fefca1db90c94f/40601/preview.png 945w,
/static/0934b66d1336f77082fefca1db90c94f/78612/preview.png 1260w,
/static/0934b66d1336f77082fefca1db90c94f/f02b9/preview.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The boxes on the right are positioned statically. This is the default when
you don’t specify a &lt;code class=&quot;language-text&quot;&gt;position&lt;/code&gt; property, therefore a statically positioned
box is also known as a &lt;strong&gt;non-positioned&lt;/strong&gt; box. I’ve added some negative
margins so they overlap with one another.&lt;/p&gt;
&lt;p&gt;On the left-hand side, you can type some styles which will be applied to
the boxes. Notice that you can also share the setup by copying the URL.
Let’s get started now!&lt;/p&gt;
&lt;h2 id=&quot;ordering-matters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ordering-matters&quot; aria-label=&quot;ordering matters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Ordering matters&lt;/h2&gt;
&lt;p&gt;Here’s the HTML that powers the page:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;html&quot;&gt;&lt;pre class=&quot;language-html&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;purple&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;blue&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;green&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;yellow&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;red&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, ordering in the HTML matters. The red box is positioned
above the rest because it appears later in the code.&lt;/p&gt;
&lt;h2 id=&quot;z-index-doesnt-work-by-itself&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#z-index-doesnt-work-by-itself&quot; aria-label=&quot;z index doesnt work by itself permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;z-index doesn’t work by itself&lt;/h2&gt;
&lt;p&gt;Look at &lt;a href=&quot;https://z-index.juliu.is/?css=p%2Bz-index%3A%209999&quot;&gt;this&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fdba47018abddc6f09300b7df6e0c4ac/f02b9/z-index-alone.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAADxklEQVR42o2UW0ybZRyHe+uFCdsEWkrX7yvLOLYdDtiQgS1ksSuFlmKhJw7TRKFlnASBKcZjIFEOm4yNkjDHBdxxiEbZosky2dhArwhcSADvuPGCQDAchMf0IxQJJuxNnvzyv3if5P99v7wytVqNQqEIERkZiVwuJzw8HEEQyM7OxmYrwJx7DZs9nyRtAspoBWpBxVl1NGrhLBqNBlEUJWQ6nY7i4mLMZjMmkwmr1RoiPz8fu92O0WgkKfYiF5OukJz4BskJ6RKvJ2aQFJuMIAqSNIisqKiInZ0dtra2pPy/8/DRBNbLtdTb71OV18uNvLv483qpt92nMKsGlTqKGE3MvtDtdnPSefLrYyxpfmpsASpyu6nMvUWFuZvq/D5smf6jwpSUFOrq6vD7/fh8PikPCM41NbUU2K04shqotvZRabmFz3KbSks31dYAtswqVGrloTAnJ4exsTGGh4ePMTQ0xOjIKB99fBN7Rh21+X1UmHqoMPXy/ls91Fr6sWdUoIqOOBR6vd4TV34xPUVeqh9/4QA+VzvVni+54fmCSuc9rl1tRpWgRRNzDk3wL1ssFubn55mbmzvG7Owsy8t/0tffh+NSNebK76mZMNE5eZ6OyfOY7rUR0TqDsn4IMTYBjaBGptfrKS8vx2azSVU5yAOCtTEYjeg1OuKcn1P/xETbTDRtv6tID3xN2KezKJtHEWMT94UOh4Pd3V2pMtvb21IesLm5Ka3808RDwsNeIcpey2ePbTx/Ec+zaS13R95D/OopisZRYg6EL1ObZ1PPUZx6lfCCm3i/C8BMKvyWzt9Tb6L95hGnGn5AiI1HDArT0tJobW2lqamJhoYGGhsbQwTnlpYWXB4vguIMp/OaMX87CpOX4Gk6f/1ylcvtPyJ8MIIuQcs5UUBmMBikigwMDBAIBOjv7w8RnAcHB2n8sAl1eBhnij8hr/1nqChkz+dkp9LNUnkVf5T4WbYXYdPqkHk8nhNXnp6eQf7aaSJTs7HnXgdHKbuOMikpdoPTA55y3BeSkQUfgKWlJRYXF4+xsLDAysoKgw8eoFREoVApccTHgqeMPVeJxK6rlH9cpeAqxam/sF8bl8t1pCrHamMwoBEEIgUBhz4Z3GXsOkvY+w8hYWFhIRsbG6yvr7O2tiblAaurq+zt7TE+Pk6UXI5CFHlbp5cubxd72XGWhAgJX6Y2k5OTyCMikIuidImSd8F7/Sgl7+ANfsOMjAy6urro7Ow8RkdHBz09PdLLo4qORiWKXImL506WkduZBm5nHdKTZSQrLp5/AXt6slmm3iKgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;z-index by itself&quot;
        title=&quot;&quot;
        src=&quot;/static/fdba47018abddc6f09300b7df6e0c4ac/f058b/z-index-alone.png&quot;
        srcset=&quot;/static/fdba47018abddc6f09300b7df6e0c4ac/c26ae/z-index-alone.png 158w,
/static/fdba47018abddc6f09300b7df6e0c4ac/6bdcf/z-index-alone.png 315w,
/static/fdba47018abddc6f09300b7df6e0c4ac/f058b/z-index-alone.png 630w,
/static/fdba47018abddc6f09300b7df6e0c4ac/40601/z-index-alone.png 945w,
/static/fdba47018abddc6f09300b7df6e0c4ac/78612/z-index-alone.png 1260w,
/static/fdba47018abddc6f09300b7df6e0c4ac/f02b9/z-index-alone.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That’s rule number one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;z-index works only on positioned elements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; only works on elements that have a &lt;code class=&quot;language-text&quot;&gt;position&lt;/code&gt; property set to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;relative&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;absolute&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;fixed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;sticky&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://z-index.juliu.is/?css=p%2Bposition%3A%20relative%3Bz-index%3A%209999&quot;&gt;There&lt;/a&gt; we go:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/398562e10636c6bc7e9aa822c0b3d584/f02b9/z-index-positioned.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAADwUlEQVR42o2UXUxbdRiHe+uF0W3CWqD0nLKMwSgdG2MbX7YgRqBfFCr0C5jGhLbI10BgDhMTE3chsDFA1yaQsQQSlwyIRrdFE6M4EG80BC4kgHdcIAmBYAgffcw5CIhcsH/y5D3vxf/Jec/55VVoNBqUSqWMSqWSkZ4jIiIQBIGcnBxstiIKCvOx2S0k6RKJjlGhEdTEamLQCLFotVpEUZRR6HQ6SktLMZvN5OXlkZ+fj9VqlbFYLNjtdoxGI0nxl7iUlEnK+XRSEq/JXDyfQVJ8CoIoyFIJRUlJCUtLSywvL8tsb2/z//P02ROsV+tosPdTbe7lffPnBMy9NNj6Kc6uRa2JIk4btyt0uVwcd3786QdMaQFqbUGqCu/gK7xLVcEdaiz3sWUFDgtTU1NpaGggEAjg9/vluofU19bWUWS34shulAWSzFfYRVXhXWosQYqyqlFrog+Eubm5jIyMMDQ0dITBwUGGHw/z4a2b2DPqqbEGZaHf1CW/aY01RFGmH3VM5IHQ4/EcO/Ivk+OYLksjh/CZdoU+078j59wgJlFHXNwZtNJfNplMzMzMMD09fYSpqSkWFv4kGPqCovR66q0hfG/dw5/fgy+/l4Y3O7CWPySi6RHas4loBQ0KvV5PZWUlNptNjspe3UOKjcFoRBeXzMWiW9Q99NL2ZTptjzJ545N2NC0TRLWMIMaf3xU6HA52dnbY2tpic3NTrntsbGzII3/75CkRr7yEsriej8dNTP6mZeL3s/R89R6xn46jahombk/4IrF5Pj6B6sTLRNpu4ukPweQVmEzn7+evk/zZM040fo0Qn4AoCdPS0mhra6O5uZnGxkaampr2kfrW1lacbg+C6hQnzS0U3BuGsSvw8zX++j6Pq7e/QbjxmOREHWdEAYXBYJAj0tfXRzAYJBQK7SP1AwMDNH3QjCbiVU6VfoT59ndQVUzYX8aWz8V8ZTV/eAMs2N/GpktG4Xa7jx15cvJXlK+d5PTlHOyF18FRzo6jQq6UuqDMDe5KXBdSUEgLYH5+nrm5uSPMzs6yuLjIwIMHRKuiUKmjcSTEg7uCsNMrs+MsZ9tZDs5yyvQXdmPjdDoPReVIbAwGtILAaUHAoU8BVwU7ZV7C/2FfWFxczPr6Omtra6yursp1j5WVFcLhMKOjo0RJ+1IUKUnWy5c3Sz1slXn32Re+SGzGxsZQRkaiFEX5Et53wXP9MN538EjfMCMjg87OTjo6Oo7Q3t5Od3e3vHnUMTGoRZHMcwn0ZBvpyjLQlX1Ad7aR7HMJ/AOB0bC2FzVsoAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;z-index positioned&quot;
        title=&quot;&quot;
        src=&quot;/static/398562e10636c6bc7e9aa822c0b3d584/f058b/z-index-positioned.png&quot;
        srcset=&quot;/static/398562e10636c6bc7e9aa822c0b3d584/c26ae/z-index-positioned.png 158w,
/static/398562e10636c6bc7e9aa822c0b3d584/6bdcf/z-index-positioned.png 315w,
/static/398562e10636c6bc7e9aa822c0b3d584/f058b/z-index-positioned.png 630w,
/static/398562e10636c6bc7e9aa822c0b3d584/40601/z-index-positioned.png 945w,
/static/398562e10636c6bc7e9aa822c0b3d584/78612/z-index-positioned.png 1260w,
/static/398562e10636c6bc7e9aa822c0b3d584/f02b9/z-index-positioned.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Would you be able to guess what happens when we remove the &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt;
property from this example? Go on, I’ll wait.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://z-index.juliu.is/?css=p%2Bposition%3A%20relative&quot;&gt;This&lt;/a&gt; is what we see:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e896fb1635a9168646b81b937f7ad11d/f02b9/no-z-index.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAADu0lEQVR42o2UXUybVRjHe+uF0W3CWmjp+7bLGIzSsTG28WULYgQKLcUK/QKmMaEtAmUgMIeJiYm7ENgYoLYJZCyBxCUDotFt0cQoDqw3GgIXEsA7brwgEITw9TPviwWRC3aSX548F+eX85zzz1FotVpUKtUhlEolMTExCIJAXl4eNlsZRcWF2OylpBiSiVer0AoaErRqtEICOp0OURRlFAaDgYqKCiwWCwUFBRQWFmK1WmVKS0ux2+2YzWZSEi9xKSWbtPOZpCVfk7l4PouUxDQEUZClEgqHw8Hm5iZbW1usr6+zvb3N/9eTp4+xXm2kyT5IXUk/75V8RqCknybbIOW5DWi0ceh1+j2hy+XiuPXjTz9gyQjQYAtRW3wHX/FdaovuUF/6BbacwGFheno6wWCQQCCA3++XaxSpb2hopMxuxZHbLAskma+4h9riu9SXhijLqUOjjT8Q5ufnMzY2xsjIyBGGh4cZfTTKB7duYs8KUm8NyUK/pUc+ab01TFm2H4069kDo8XiOHfmXyCSWy9LIYXyWPaHP8u/IeTdQJxvQ68+gk15Zet3Z2VlmZmaOMD09zeLin4TCn1OWGSRoDeN74x7+wj58hf00vd6FteoBMS0P0Z1NRidoURiNRmpqarDZbHJUojWKFBuT2YxBn8rFsls0PvDS8WUmHQ+zee3jTrRtU8S1jSEmnt8TSrHZ2dmRYxONT5SNjQ155G8fPyHmpRdQlgf5aNJC5DcdU7+fpe+rd0n4ZBJVyyj6qPB5YvNscgrViReJtd3EMxiGyBWIZPL3s1dJ/fQpJ5q/RkhMQpSEGRkZdHR00NraSnNzMy0tLftIfXt7O063B0F1ipMlbRTdG4WJK/DzNf76voCrt79BuPGI1GQDZ0QBhclkkiMyMDBAKBQiHA7vI/VDQ0O0vN+KNuZlTlV8SMnt76C2nF1/JVs+Fws1dfzhDbBofwubIRWF2+0+duRI5FeUr5zk9OU87MXXwVHFjqNarlS4oNIN7hpcF9JQSB/AwsIC8/PzR5ibm2NpaYmh+/eJV8Wh0sTjSEoEdzW7Tq/MjrOKbWcVOKuoNF7Yi43T6TwUlSOxMZnQCQKnBQGHMQ1c1exUetn9D/vC8vJy1tbWWF1dZWVlRa5RlpeX2d3dZXx8nDilEpUo8maqUd68WeFhq9K7z77weWIzMTGBMjYWpSjKm/C+A57rh/G+jUe6w6ysLLq7u+nq6jpCZ2cnvb298s+jUavRiCLZ55LoyzXTk2OiJ/eA3lwzueeS+AcH2bEuMfpwvQAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;no z-index&quot;
        title=&quot;&quot;
        src=&quot;/static/e896fb1635a9168646b81b937f7ad11d/f058b/no-z-index.png&quot;
        srcset=&quot;/static/e896fb1635a9168646b81b937f7ad11d/c26ae/no-z-index.png 158w,
/static/e896fb1635a9168646b81b937f7ad11d/6bdcf/no-z-index.png 315w,
/static/e896fb1635a9168646b81b937f7ad11d/f058b/no-z-index.png 630w,
/static/e896fb1635a9168646b81b937f7ad11d/40601/no-z-index.png 945w,
/static/e896fb1635a9168646b81b937f7ad11d/78612/no-z-index.png 1260w,
/static/e896fb1635a9168646b81b937f7ad11d/f02b9/no-z-index.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;It turns out that positioned boxes appear on top of non-positioned boxes.
If you’re inclined, the &lt;a href=&quot;https://www.w3.org/TR/CSS2/zindex.html&quot;&gt;spec&lt;/a&gt; goes
into &lt;strong&gt;much&lt;/strong&gt; more detail.&lt;/p&gt;
&lt;p&gt;But if all the boxes are positioned, we revert to following the order in
the HTML source. Look at
&lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%7Cp%2Bposition%3A%20relative%7Cr%2Bposition%3A%20relative&quot;&gt;this&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d8f35f9142c93f271bd95751879bf1fb/f02b9/all-positioned.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD3klEQVR42o2UW0zbZRiHufXChG3CWqDr/1+WcWw7HLBhB7YkRGgLLWWV0nKaJgqUAVYQmGI8BhLlMEQY5TDGBXAFIRpliybLZGMDvSJwIQG8gpB5QUIiBCiP6Z8AIhfjTZ68+S7eX/J935M3QKlUIpfLjyGTyQgKCkIQBFJTU7FaszGaMrDasohVRxMaJkcpKLigDEMpXEClUiGKokSAWq0mNzcXs9lMWloaGRkZWCwWiaysLGw2GwaDgdiIK1yJvU5czBvERSdJvB6jIzYiDkEUpFA/AXa7ne3tbXZ2dtjc3GR3d5f/14OHE1iuVeGx3aM8s5NbmV24MzvxWO+Rk1KJQhlCuCp8P9DpdPKyevzbI8yJbiqtXkpMbZSa7lBibKMiqxtrsvt4YHx8PB6PB7fbfYKysjIqK6vItlmwp1RTYemm1HyHMnM7peY2KixerMnlKJShR4F6vZ6BgQF6e3vp6uqir6+PkZERhoeHGRoaYmx0jI8/uY1N9wFVWd2UpHdQkt7J+291UGXuwaYrQREWfBTocrleeuXn01NkJrhx5/RTltdEhesrbrm+pNRxl4y0OhTRalThF1H5f9n/u/Pz88zNzZ1gdnaW5eW/6O7pxn61AmPpD1ROpNMyeYnmyUuk320kuGGGUM8QYkQ0KkFJgFarpbi4GKvVKqly0A/wa6M3GNCqNEQ6vsDzOJ3GmTAa/1CQ5P2GwM9mCa0bQ4yI2Q/0a+Pz+SRtDvQ5YGtrS7ryzxMPCAp8hRBbFZ8/svLseRRPp9V0jb6H+PUT5DVjhB8Enkabp1PPkJ95laDs2+QPeGEmAX5P4p+pN1F/+5Az1T8iREQh+gMTExNpaGigtraW6upqampqDvGf6+vryXPlI8jPcTazDuN3YzB5FZ4k8fevaVxr+gnhw1E00WouisK+Nn5F+vv78Xq99PT0HOI/Dw4OUvNRLcqgQM7lfkpm0y9QksNemYOdUidLxeX8WeBm2fY2VrXmdNpMT88ge+0s5xNSsZlugr0Qn71I6uQ6weECVzHOy3EE+BfA8vIyS0tLhywuLkosLCywurrK4P37hMpDkCtCsUdFgKuIvbwCCV9eIbt5hZBXiEN7mQCNRkNOTg5Go1HaNCaT6Zg6kjZ6PSpB4LwgYNfGgbMIn6OAvf9wGJidnc3a2hovXrxgZWVF6hsbGxLr6+vs7e0xPj5OiEyGXBS5odFKw9u5+ew4Cg45DDyNNpOTk8iCg5GJojREwbuQf/M4Be+Q739DnU5Ha2srLS0tJ2hubqajo0PaPIqwMBSiyPXIKL5PMdCerKc95YiOFAMpkVH8CzcasN9C8iVSAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;all positioned&quot;
        title=&quot;&quot;
        src=&quot;/static/d8f35f9142c93f271bd95751879bf1fb/f058b/all-positioned.png&quot;
        srcset=&quot;/static/d8f35f9142c93f271bd95751879bf1fb/c26ae/all-positioned.png 158w,
/static/d8f35f9142c93f271bd95751879bf1fb/6bdcf/all-positioned.png 315w,
/static/d8f35f9142c93f271bd95751879bf1fb/f058b/all-positioned.png 630w,
/static/d8f35f9142c93f271bd95751879bf1fb/40601/all-positioned.png 945w,
/static/d8f35f9142c93f271bd95751879bf1fb/78612/all-positioned.png 1260w,
/static/d8f35f9142c93f271bd95751879bf1fb/f02b9/all-positioned.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;And at that point, specifying a &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; &lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%3Bz-index%3A%201%7Cp%2Bposition%3A%20relative%3Bz-index%3A%202%7Cr%2Bposition%3A%20relative&quot;&gt;does
work&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/03a454c21d00f1e6821732738e1d70e1/f02b9/finally-z-index.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD6UlEQVR42o2UXUxbZRjHe+uFMXODtdDSc4obg1G+JsRBKS1xRuh3C+N76BYM0PFpK2OOJSZLXFxgG7KCbQAHBogzInNG8MIsioKoFwuSLVk2vIIMLliCCQhjP3MOg4lebG/yy/O+F+eX58n551FotVqUSqWMSqWSke5hYWEIgkB2djZOp4tcSw5Ot514fRyRahVaQUOUVo1WiEKn0yGKooxCr9dTUFCAzWbjyJEj5OTk4HA4ZOx2O263G7PZTHzMIQ7FG0g+mE5y3GGZlIMZxMckI4iCLJVQ5OXlsbCwwNLSEisrKzx69Ij/nrHvRnG8Vk+ju5eTtgA1tk68tgCNzl48xjo02giiddGbwuLiYp51fvjxJtY0L3XOIJWWS1RZLlOZe4la+yc4M707hampqfh8PmpqavB6vTuorq6mrq4el9tBvtEnCyRZlaWdSstlau1BXJkn0WgjnwqzsrLo6uoiEAjQ2dlJd3c3Q0NDDA4OMjAwwPCXw7x/5jTujAZqHUFZWG1tlzutdYRwGarRqMOfCktKSp458i9TE1hTpZFDVFk3hVXWJyNnv4s6Tk909CvopL9stVq5c+cOt2/fZmZmZgfT09PMzv5JMNSFK72BBkeIqjc/pjrnClU5ARrfaMNxrJ8w/zV0++PQCVoUiYmJlJeX43Q65ahs1S2k2JjMZvTRCaS4zlDfX0bL5+m0XDPw+rlWtKcmiTj1FWLMwU1hfn4+GxsbrK+vs7a2JtctVldX5ZG/HR0j7KUXUHoa+GDCwtQtHZO39tNxowLNhxMo/cNEbwmfJzY/T0yi2vUi4a7TlPaGYPIwTBr4a9xM0oUx9vi+RoiJRZSEaWlptLS00NTUJMfH7/dvI72bm5spKilFVO3mZVsz9itfwG96+D2Rv38ykPLRKCrfdfRxevaJAgqTySRHpKenh2AwSCgU2kZ69/X14X+viajwXYR7zpIRvMn10ROMjFXQf6OW3RfGiWr5nj/ySvDExz9fbKamfmXvnt2oX83CYPfyWcV5Pq04T1/FeQYqz/HNO2eh9DgliUkopAUwOzvL/fv3t7l3757M3bt3mZ+fp+/qVSJVESg1kRTF7oPCAjh69AnSvRCKjlEoCRMSEvB4POTm5sqbxmKx7IiOHBuTCZ0gsFcQyEtKgeK3WCsqZ/1fUFS+KXS5XDx48IDFxUXm5ubkury8LPPw4UMeP37MyMgIEdK+FEXyEhLlbtYKSlkvLNtmu8Pnic34+DjK8HCUoih/RNkJKH17J2XHKU1KRpGRkcHFixdpa2v7H62trXR0dMibR6NWoxFFDAdiuWI0055pot34lA6jGeOBWP4BUamuQD9uMQkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;finally z-index&quot;
        title=&quot;&quot;
        src=&quot;/static/03a454c21d00f1e6821732738e1d70e1/f058b/finally-z-index.png&quot;
        srcset=&quot;/static/03a454c21d00f1e6821732738e1d70e1/c26ae/finally-z-index.png 158w,
/static/03a454c21d00f1e6821732738e1d70e1/6bdcf/finally-z-index.png 315w,
/static/03a454c21d00f1e6821732738e1d70e1/f058b/finally-z-index.png 630w,
/static/03a454c21d00f1e6821732738e1d70e1/40601/finally-z-index.png 945w,
/static/03a454c21d00f1e6821732738e1d70e1/78612/finally-z-index.png 1260w,
/static/03a454c21d00f1e6821732738e1d70e1/f02b9/finally-z-index.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Using the powers of &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; we were able to reverse the default stacking order of
the boxes. Go us.&lt;/p&gt;
&lt;h2 id=&quot;a-new-mystery&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-new-mystery&quot; aria-label=&quot;a new mystery permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A new mystery&lt;/h2&gt;
&lt;p&gt;Let’s look at &lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%7Cr%2Bposition%3A%20relative%7Cy%2Bposition%3A%20relative%3Bz-index%3A%201%3Bheight%3A%20200px&quot;&gt;this
example&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/24196cc40311cf0559114651d8c9e25d/f02b9/mystery.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD9klEQVR42o2UXUibVxyHvd3FwLaoiSbN+8ZSrR9Jba2fNSRupRqjibGZxsTqOkaNadX5Ndtt4L5ww/mJrTXqamWoV4rsy/ZKWmttZBdF9GKizhuldhcFYVideUZeseIKcwce/pwD54H/Ob9zAlQqFSEhIQeQyWQEBQUhCALp6elYLLkYszKxWHOIiY0iTCFHJSg5rlKgEo6jVqsRRVEiQKvVUlxcjNVqJScnB7PZ/Br/3L9uMBiIiTjL2ZjzxEWnEBeVLHEmOpWYiDgEUZCkfgLy8/M5bNx/MI45qZIq612uZd/menYX7uzbVFnukqerQKkKJVwdviu02+2HCh8+msCU4KbC4qE0qw1XVjulxjbKc7qxpLkPCuPj46mursbtdr9BWVkZFRWV5FrN2HQ1lJu7cZnaKTN14DK1UW72YEm7hlIVti/U6/X09/fT29tLV1cXfX19DA8PMzQ0xODgIKMjo3zy6U2sqR9RmdNNaUYnpRm3uXqxk0pTD9bUUpSK4H2hw+E4tOWn3idkn3PjzvueMvs3lDu+4rrjS1wFd8i8UI8yKhZ1+AnU/ls2mUzMz88zNzf3BrOzsywv/0F3Tze2xHKMrh+pGM+gZfIkzZMnybjTSPBnM4RVDSJGRKEWVLuxKSkpwWKxSFHZq3v4Y6M3GNCqNUQWfEHVwwwaZxQ0/qYk2dNEYMMsYfWjiBHRu0KbzcbOzg7b29tsbW1JdY/NzU2p5V/H7xMU+Bah1ko+n7Aw7Y1kyhtL1+iHiF8/Rl47SviesLCw8NAznHoyjfzI2wTl3sTZ7wFvAniT+euxntjvHnCk5ieEiFOIfmFiYiINDQ3U19dTW1tLXV2dVP3U1NRw48YN7A4ngvwYR7PrMd4agafnwJvEn4/eJenbXxCqRtBExXJCFAhIS0ujvb2dlpYWmpqa6OjokCLU09ODx+NhYGCA2rqPUQUHcszaQHbfzzB9Dp83he0JHUsuF7873Cxb38MSq9l9eq9evfrPlr3eGWRBRwnRvoP1agE8S2DnWSJMpcCVfLA5wVlC4ek4AvwfwMrKCsvLyywtLUksLi5KLCwssLa2xsC9e4SFypGHKrCliPDDRXwDF/D1ZrBT4uTv/GKwX6ZAe5oAjUZDXl4eRqORzMxMsrKyDkRHio1ej1oQCBEEbJozYCthJ68Y36VifAWX8dmL9oW5ubk8f/6c9fV1VldXefHiBRsbGxIvX77E5/MxNjZGqEyGXBS5pNFC4WW2CpxsSxRJvBb+n9hMTk4iCw5GJorSJoo+AOf7Bym6gtN/hqmpqbS2tkq3/G+am5vp7OyUfh6lQoFSFDkfeYpbOgMdaXo6dPt06gzoIk/xD7rxsx7O8HDYAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;mystery&quot;
        title=&quot;&quot;
        src=&quot;/static/24196cc40311cf0559114651d8c9e25d/f058b/mystery.png&quot;
        srcset=&quot;/static/24196cc40311cf0559114651d8c9e25d/c26ae/mystery.png 158w,
/static/24196cc40311cf0559114651d8c9e25d/6bdcf/mystery.png 315w,
/static/24196cc40311cf0559114651d8c9e25d/f058b/mystery.png 630w,
/static/24196cc40311cf0559114651d8c9e25d/40601/mystery.png 945w,
/static/24196cc40311cf0559114651d8c9e25d/78612/mystery.png 1260w,
/static/24196cc40311cf0559114651d8c9e25d/f02b9/mystery.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Out of the three positioned boxes, the yellow one has &lt;code class=&quot;language-text&quot;&gt;z-index: 1&lt;/code&gt;, and
therefore appears on top. Good, the world is making sense.&lt;/p&gt;
&lt;p&gt;But what if we give a &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; to the blue box, the parent of the yellow box? Our
example would look like
&lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%3Bz-index%3A%200%7Cr%2Bposition%3A%20relative%7Cy%2Bposition%3A%20relative%3Bz-index%3A%201%3Bheight%3A%20200px&quot;&gt;this&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f02b9/mystery-two.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD7klEQVR42o2UW0zbVRzHefXBhG0CLdD1/y/LuLYdLsiQFSjJIrSFltZKL1w2TRQoNxEQ5iV4CyTIVWRQYHM8AE8QolG2aLJMNjbQJ0IgEkBeIIAPJCSGi/Ax/RNAfBBP8skv5yTnk/zO+Z7jp1QqCQoKOoVMJiMgIABBEEhNTcViycJgTMdizSRGHUVIqByloOCiMhSlcBGVSoUoihJ+Wq2W/Px8rFYrmZmZmM3mY3xz37perycm/CpXY64TG/0qsVEJEi9HJxITHosgCpLUh192djZnjQcPxzBfK6fCeo/ijE5KMu7gyeikwnIPW1IZCmUwYaqwQ6HT6TxT+PjnR5he8VBm8VJgbKXQ2EaBoZXSzG4sOs9pYVxcHJWVlZSUlFBcXIzH4zmmqKiIsrJysqxm7EmVlJq7KTS1UWRqp9DUSqnZi0VXjEIZciJMTk6mq6uLzs5Oib6+PoaGhhgcHGRgYICR4RE++PA21sR3Kc/spiCtg4K0Tt55rYNyUw/WxAIUoYEnQrfbfWbLzycnyIjz4LHdpcjZQKn7c0rcn1Ho6CL9Rg2KKDWqsEuofLdsMpmYm5tjdnaWmZmZU0xPT7O09DvdPd3Y40sxFH5L2VgazeOXaRq/TFpXPYEfTRFSMYAYHoVKUJ7ExmKxSFE5qkf4YpOi16NVaYhwfErF4zTqp0Kp/1VBgrcR/7ppQmpGEMOjD4V2u539/X329vbY3d2V6hHb29tSyz+MPSDA/wWCreV88sjCs+eRPJ1Uc2f4bcQvniCvGiHsSOhyuc48w6cTz5Cfe5GArNvkfOOFqTj4JYE/J5JRf/mQc5XfIYRHIvqE8fHx1NXVUVNTQ1VVFdXV1VL14YtTbW0tTncOgvwC5zNqMHw1AuPx8CSBP366wbWG7xHeG0YTpeaSKOCn0+loa2ujubmZxsZG2tvb6e3tpaenB6/XS39/P1XV76MM8OdC9sdkNPwIBTYOihzsFbpYvFnMb7kelqxvYFFrDp/ezs7Of7Y8OTmF7KXzBMWlYjXeAnse+/Z8qZLtAocb3DdxXYnFz/cBLC8vs7S0xOLiosTCwoLE/Pw8q6ur9N+/T4g8GLkiBHtkOLjzOXDmSuw78/jLmQfOPBzaK/hpNBpsNhsGg4H09HSMRuOp6EixSUlBJQgECQJ2bSy48tl35HLwD46FWVlZrK2tsb6+zsrKChsbG2xtbUlsbm5ycHDA6OgowTIZclHkdY1W2rybncOeI/eYY+H/ic34+DiywEBkoihtIvctyLl1mtw3yfGdYWJiIi0tLdIt/5umpiY6Ojqkn0cRGopCFLkeEcnXSXradSm0J53QkaQnKSKSvwEQvrCL106wVAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;mystery part two&quot;
        title=&quot;&quot;
        src=&quot;/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f058b/mystery-two.png&quot;
        srcset=&quot;/static/f3119574dc5e9f1877b5d6d8f6e17fd7/c26ae/mystery-two.png 158w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/6bdcf/mystery-two.png 315w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f058b/mystery-two.png 630w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/40601/mystery-two.png 945w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/78612/mystery-two.png 1260w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f02b9/mystery-two.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What’s happening here? Our yellow box is now rendered below the red one?!
All this because we added a &lt;code class=&quot;language-text&quot;&gt;z-index: 0&lt;/code&gt; to the blue one?! The world is
making no sense again. 😿&lt;/p&gt;
&lt;p&gt;Let’s take a bit of a detour…&lt;/p&gt;
&lt;h2 id=&quot;auto-is-not-zero&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#auto-is-not-zero&quot; aria-label=&quot;auto is not zero permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Auto is not zero&lt;/h2&gt;
&lt;p&gt;If we don’t set the &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; property of an element, its default value is
going to be &lt;code class=&quot;language-text&quot;&gt;auto&lt;/code&gt;. Such elements will appear in front of elements with
negative &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; values and below elements with positive &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt;
values.
&lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%7Cp%2Bposition%3A%20relative%3Bz-index%3A%201%7Cr%2Bposition%3A%20relative%3Bz-index%3A%20-1&quot;&gt;This&lt;/a&gt;
should convince you that I’m not lying:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1786f16b25da7227a7897b16f922c345/f02b9/z-index-auto.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD3klEQVR42o2UWUycVRiGufXCmEqhMzDD/P9gS1mGrUgsDDhDxEhnmA0oe4ttMMBUNkFKLU1MmkhsgBZZdIatYIBYI1JrBC9MoyiIetEgJISwXJCQEC5IMAHZHvP/FGjlopzkyTnn4jz5vpw3n4dGo0GhUMgolUoZ6ezl5YUgCCQkJGCz2blgSsLmsBCiC8JXpUQjqPHTqNAIfmi1WkRRlPHQ6XSkp6djNptJTEwkKSkJq9UqY7FYcDgcGI1GQgLOcS5ET0RwDBFB52Uig2MJCYhAEAVZKuGRmprK8vIyq6urrK+vs729zf/X8I9DWN8opdzRybXkFt5PbsWZ3EK5rZOU+BLUGh/8tf57wqysLF60fv7lMeZoJyU2FwWmuxSa7lFw4S7Fli+wxTmfF0ZFRVFeXo7T6TxCUVERJSWl2B1W0uIrZIEkKzQ1UmC6R7HFhT3uGmqN76HQYDDQ1dVFW1sbra2ttLe309/fT19fH729vQx8M8BHN2/giC2j2OqShUXmRrnSYqsbu74Itcr7UJidnf3Cln8fH8X8utSym0LznrDQ/LTlhA9QBenw938NrfTL0u9OTU0xOTl5hImJCebnF3C5P8ceU0aZ1U3hO59RlNRMYVIL5W/XY73Ug1flA7RngtAKGjzCwsLIy8vDZrPJUdnf95FiYzAa0fmHEmm/SWlPLjVfxVDzQM9bt+vQXB/D5/q3iAHBe8K0tDR2dnbY2tpic3NT3vfZ2NiQW/5haBivV15CkVLGx6Mmxp9oGXtyhqZH+ag/GUVROYD/vvA4sfltdAzliZfxtt8gp9MNY+dhTM8/I0bC7wxzsuI7hIBAREkYHR1NTU0NVVVVVFRUUFlZeYB0r66uJjM7B1HpyavJ1Viav4Y/dfBXGP/+qify0yGUFQ/RBek4LQp7sZEi0tHRgcvlwu12HyDdu7u7qfywCj/vE3in3CLW9ZiHQ1cZHM6n51ExnndG8Kv5ib9Ts0kJCTlebMbH/+DUSU9UUW+itzj5Mr+WrvxauvNr6S24zffv3YKcK2SHheMhDYD5+Xnm5uYOmJ2dlZmZmWFpaYnu+/fxVfqgUPuSGXgaMtLh4sWnSOcMyLxEhiQMDQ1FGhAmk0meNNL+bHTk2BgMaAWBU4JAangkZOWxmXmZrWcg8/KeUHo8PT3NwsICi4uLrKyssLa2JiNNoN3dXQYHB/GR5qUokhoaJlezmZ7DVkbuAQcVHic2IyMjKLy9UYii/Ijcq5Dz7vPkXiEnPAKP2NhYGhoaqK+vP0JdXR1NTU3y5FGrVKhFEf3ZQJrjjTTGGWiMP6Qp3kj82UD+A2SHrgRhiKLrAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;z-index auto&quot;
        title=&quot;&quot;
        src=&quot;/static/1786f16b25da7227a7897b16f922c345/f058b/z-index-auto.png&quot;
        srcset=&quot;/static/1786f16b25da7227a7897b16f922c345/c26ae/z-index-auto.png 158w,
/static/1786f16b25da7227a7897b16f922c345/6bdcf/z-index-auto.png 315w,
/static/1786f16b25da7227a7897b16f922c345/f058b/z-index-auto.png 630w,
/static/1786f16b25da7227a7897b16f922c345/40601/z-index-auto.png 945w,
/static/1786f16b25da7227a7897b16f922c345/78612/z-index-auto.png 1260w,
/static/1786f16b25da7227a7897b16f922c345/f02b9/z-index-auto.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;So in a way that element behaves as if we set &lt;code class=&quot;language-text&quot;&gt;z-index: 0&lt;/code&gt;. Indeed, if we
add that CSS rule, we see no notable changes in the
&lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%3Bz-index%3A%200%7Cp%2Bposition%3A%20relative%3Bz-index%3A%201%7Cr%2Bposition%3A%20relative%3Bz-index%3A%20-1&quot;&gt;output&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e447a471c677ad3ed068d42015735809/f02b9/z-index-zero.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD5UlEQVR42o2UXUybVRjHe+uFMZPBWmjp+xY3Bmv5mhA3CrREjKylX8D4aBm6BQN0wECQMccSkyUSF2BDQNYGcGCAOCMyZwQvzKIoiHqxIBkL4eOChGThgmQmm3z9zPsyYOjFOMkv55yL88vz5PzzKLRaLUqlUkalUslI58DAQARBIDU1FYfDySlLOg6XDb0hkhC1Cq2gIVSrRiuEotPpEEVRRmEwGMjJycFqtZKWlkZ6ejp2u13GZrPhcrkwm83ow49zXG8k9thJYiNPyMQdS0QfHosgCrJUQpGVlcWjR49YWVnhyZMnrK+v89818sMw9jcuUOXq5nxGO2UZn+HNaKfK0U1mcgUabTBhurAtYX5+Pi9aP/18D2uClwqHj2LLdUosNyg+dZ1y200cSd69wvj4eKqrqykrK8Pr9e6htLSUiooLOF12spOrZYEkK7G0UGy5QbnNhzPpPBptyK4wJSWFjo4O2tvbZTo7OxkYGKC/v5++vj4Gvx7kw8uXcCVWUm73ycJSa4tcabndj9NYikYdtCt0u90vbPm3iTGs8VLLfkqsW8IS67OWU99HHWkgLOw1dNIvS787PT3NgwcPmJqa2sPk5CTz8wv4/B04T1ZSafdT8vanlKa3UZLeTtVbTdjP9BJYcxvdkUh0ghZFdHQ0hYWFOBwOOSrb+zZSbExmM4awKOKcl7nQW0D9lyepv23kzauNaC+OE3zxG8TwY1vC7OxsNjY2WFtbY3V1Vd63efr0qdzy98MjBL7yEsrMSj4aszBxX8f4/SO03i1C8/EYyppBwraF+4nNr2PjqA68TJDzEp5uP4yfgHEjf4+aibk2wsHqbxHCIxAlYUJCAvX19dTW1srxqamp2UG619XVkef2IKoCeDWjDlvbV/CHAf6M5p9fjMR9Moyq+g6GSAOHRQGFyWSSI9LV1YXP58Pv9+8g3Xt6eqj5oJbQoAMEZV4h0XePO8PnGBopovduOQHXRgmt/5G/stxk6vX7i83ExO8cOhiA+vUUjDYvXxQ18HlRAz1FDfQVX+W7966A5yzu6BgU0gCYn59nbm5uh9nZWZmZmRmWlpbouXWLEFUwSk0IeRGHITcHTp9+hnTOhbwz5ErCqKgopAFhsVjkSSPtz0dHjo3JhE4QOCQIZMXEQf47rOYVsvYc5BVuCaXHDx8+ZGFhgcXFRZaXl3n8+LGMNIE2NzcZGhoiWJqXokhWVLRczWqOh7Xcgh12KtxPbEZHR1EGBaEURfkRBefA8+5eCs7iiYlFkZiYSHNzM01NTf+jsbGR1tZWefJo1Go0oojxaARtyWZakky0JO/Smmwm+WgE/wL66K3ssiM0TgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;z-index zero&quot;
        title=&quot;&quot;
        src=&quot;/static/e447a471c677ad3ed068d42015735809/f058b/z-index-zero.png&quot;
        srcset=&quot;/static/e447a471c677ad3ed068d42015735809/c26ae/z-index-zero.png 158w,
/static/e447a471c677ad3ed068d42015735809/6bdcf/z-index-zero.png 315w,
/static/e447a471c677ad3ed068d42015735809/f058b/z-index-zero.png 630w,
/static/e447a471c677ad3ed068d42015735809/40601/z-index-zero.png 945w,
/static/e447a471c677ad3ed068d42015735809/78612/z-index-zero.png 1260w,
/static/e447a471c677ad3ed068d42015735809/f02b9/z-index-zero.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;But things changed a lot! Giving a value to &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; to a relatively
positioned box creates a new &lt;strong&gt;stacking context&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A stacking what?
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context&quot;&gt;MDN&lt;/a&gt; says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The stacking context is a three-dimensional conceptualization of HTML
elements along an imaginary z-axis relative to the user, who is assumed
to be facing the viewport or the webpage. HTML elements occupy this space
in priority order based on element attributes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I thought this is what we were trying to do all along. Let’s keep reading.&lt;/p&gt;
&lt;p&gt;The interesting part comes later:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Within a stacking context, child elements are stacked according to the
same rules previously explained. Importantly, the z-index values of its
child stacking contexts only have meaning in this parent.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That’s the key point. A stacking context will force the &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; of its
child stacking contexts to only have a local meaning. Let’s look at our
mysterious example again:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f02b9/mystery-two.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD7klEQVR42o2UW0zbVRzHefXBhG0CLdD1/y/LuLYdLsiQFSjJIrSFltZKL1w2TRQoNxEQ5iV4CyTIVWRQYHM8AE8QolG2aLJMNjbQJ0IgEkBeIIAPJCSGi/Ax/RNAfBBP8skv5yTnk/zO+Z7jp1QqCQoKOoVMJiMgIABBEEhNTcViycJgTMdizSRGHUVIqByloOCiMhSlcBGVSoUoihJ+Wq2W/Px8rFYrmZmZmM3mY3xz37perycm/CpXY64TG/0qsVEJEi9HJxITHosgCpLUh192djZnjQcPxzBfK6fCeo/ijE5KMu7gyeikwnIPW1IZCmUwYaqwQ6HT6TxT+PjnR5he8VBm8VJgbKXQ2EaBoZXSzG4sOs9pYVxcHJWVlZSUlFBcXIzH4zmmqKiIsrJysqxm7EmVlJq7KTS1UWRqp9DUSqnZi0VXjEIZciJMTk6mq6uLzs5Oib6+PoaGhhgcHGRgYICR4RE++PA21sR3Kc/spiCtg4K0Tt55rYNyUw/WxAIUoYEnQrfbfWbLzycnyIjz4LHdpcjZQKn7c0rcn1Ho6CL9Rg2KKDWqsEuofLdsMpmYm5tjdnaWmZmZU0xPT7O09DvdPd3Y40sxFH5L2VgazeOXaRq/TFpXPYEfTRFSMYAYHoVKUJ7ExmKxSFE5qkf4YpOi16NVaYhwfErF4zTqp0Kp/1VBgrcR/7ppQmpGEMOjD4V2u539/X329vbY3d2V6hHb29tSyz+MPSDA/wWCreV88sjCs+eRPJ1Uc2f4bcQvniCvGiHsSOhyuc48w6cTz5Cfe5GArNvkfOOFqTj4JYE/J5JRf/mQc5XfIYRHIvqE8fHx1NXVUVNTQ1VVFdXV1VL14YtTbW0tTncOgvwC5zNqMHw1AuPx8CSBP366wbWG7xHeG0YTpeaSKOCn0+loa2ujubmZxsZG2tvb6e3tpaenB6/XS39/P1XV76MM8OdC9sdkNPwIBTYOihzsFbpYvFnMb7kelqxvYFFrDp/ezs7Of7Y8OTmF7KXzBMWlYjXeAnse+/Z8qZLtAocb3DdxXYnFz/cBLC8vs7S0xOLiosTCwoLE/Pw8q6ur9N+/T4g8GLkiBHtkOLjzOXDmSuw78/jLmQfOPBzaK/hpNBpsNhsGg4H09HSMRuOp6EixSUlBJQgECQJ2bSy48tl35HLwD46FWVlZrK2tsb6+zsrKChsbG2xtbUlsbm5ycHDA6OgowTIZclHkdY1W2rybncOeI/eYY+H/ic34+DiywEBkoihtIvctyLl1mtw3yfGdYWJiIi0tLdIt/5umpiY6Ojqkn0cRGopCFLkeEcnXSXradSm0J53QkaQnKSKSvwEQvrCL106wVAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;mystery part two&quot;
        title=&quot;&quot;
        src=&quot;/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f058b/mystery-two.png&quot;
        srcset=&quot;/static/f3119574dc5e9f1877b5d6d8f6e17fd7/c26ae/mystery-two.png 158w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/6bdcf/mystery-two.png 315w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f058b/mystery-two.png 630w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/40601/mystery-two.png 945w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/78612/mystery-two.png 1260w,
/static/f3119574dc5e9f1877b5d6d8f6e17fd7/f02b9/mystery-two.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Setting &lt;code class=&quot;language-text&quot;&gt;z-index: 0&lt;/code&gt; on the blue box changed the meaning of the &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt;
declaration on the yellow box. Before, the yellow box was out there playing
with the big boys. Now, it can only affect stacking within the blue box.&lt;/p&gt;
&lt;p&gt;This is a great cause of frustration. No matter how high you set a
&lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; property, you will &lt;em&gt;never&lt;/em&gt; be able to ‘escape’ the parent
stacking context.  And every time you are struggling with making &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt;
work you can bet that it’s because &lt;em&gt;something&lt;/em&gt; created a stacking context
that you can’t escape from.&lt;/p&gt;
&lt;p&gt;With this newfound understanding, spend some time explaining why &lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bposition%3A%20relative%3Bz-index%3A%201%7Cg%2Bposition%3A%20relative%3Bz-index%3A%2010%7Cp%2Bposition%3A%20relative%3Bz-index%3A%202%7Cr%2Bposition%3A%20relative%7Cy%2Bposition%3A%20relative%3Bz-index%3A%205%3Bheight%3A%20200px&quot;&gt;this
example&lt;/a&gt; makes perfect sense:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3a1b4c6e74adfd5afaaa323f54c4c699/f02b9/no-mystery.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAECUlEQVR42o2UW0zTVxzH+7pkyTYd2EKx/3/ZhlxaBQNeoJUylZXSexvLTaY+jIuAMLqhcxkPJkvGQOm42UKIuKiZyRhxy2QvM5MMZC8zhEggyPRBJ2zRRBNujs/yP2waXBY9ySc5L+eT8zu/7/mpdDodarVaoNFoBMo+KioKSZLIycnB5XKTZ7Pi8jhIMSQRq9Wgk+LYqNOikzai1+uRZVmgMhgM7Nu3D7vdzp49e7BarTidToHD4cDj8WCxWEhJ2MrWlCxSk3eSmrRDkJacSUpCKpIsCamCyufzMTs7y/3795mfn+fx48c8uwZ/uIxz+xHqPL0ctndQZe+k0t5BnasXr7mGOF0M8fr4VWFhYSHPWz9dvUJ+RiU1rjBltlOU21opyztFteM0LlPlWmF6ejr19fVUVVVRWVm5hoqKCmpqjuD2OPGb64VAkZXbQpTZWql2hHGbDhOni30q3LVrF11dXXR0dNDZ2UlPTw8XLlzg/PnznDt3jv6v+/no+DE8mbVUO8NCWJEfEjetdkZwZ1UQp41+KiwqKnpuyddGh8lPV0qOUJ6/KizP/6fknPfRJhmIj38DvdJlpbuTk5NMTExw48YNwfj4uGBsbIyZmd8IR7pw76yl1hmh7J0vKLe2U2btoG5vC879Z4kKXkT/VhJ6Sbcam0AggM1mIzc3l7y8PFwu15PoKLHJtlgwxBtJcx+n7mwJJ77K4sRFE7knmtE1jBDT8A1yQvKqUDlw+/Zt7t69y9zcHI8ePWJ5eZmlpSUWFhZEyd9fHuT1V14i1ltHcNhK669qWq5r+eTbA0ifjqAO9hP/r/BFYvPz8Aia115mg/sY/t4wsyNp/H4tnbkhM2lNg6yvv4SUkIisCLdt20ZjYyMNDQ0Eg8E1KHE6evQoBUXFyJr1rLM3kN/eD6MZMLqDP6/uJvWzQTT1AxiSDLwpS6hMJhOtra20tLTQ1NREKBSiu7ubSCRCOBymr6+P4Acfoot+lfWeRuw938FIOlzbzh9XdxPz+RW0x39k3FeENyUFlfKPFxcXWVlZ+d+SR0d/QR21jg2b38bzXgCuZwgWhk30133MpUONUHKQos1bUCkD4NatW8zMzHDz5k3B9PS0YGpqSjSr78wZYmM0aGK0+HfK8GUuf53dC925UOIHXwAK9hNQhEajEa/XK+KiTBolPv+JTXY2ekligyThN6aB/11WvKWs+EpZLliFgtJVodvt5t69e2Li3LlzR0Tn4cOHggcPHoinGBgYIEaZl7KMz7gZCvezFChmWVAieHLDF4nN0NAQ6uho1LIsDlFyCIoPrKXkIMVbUlFlZmZy8uRJ0eVnaW5upq2tTUyeOK2WOFkma1Mi7WYLIVM2IfNT2swWzJsS+Rt5A65OqBgjeAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;no mystery&quot;
        title=&quot;&quot;
        src=&quot;/static/3a1b4c6e74adfd5afaaa323f54c4c699/f058b/no-mystery.png&quot;
        srcset=&quot;/static/3a1b4c6e74adfd5afaaa323f54c4c699/c26ae/no-mystery.png 158w,
/static/3a1b4c6e74adfd5afaaa323f54c4c699/6bdcf/no-mystery.png 315w,
/static/3a1b4c6e74adfd5afaaa323f54c4c699/f058b/no-mystery.png 630w,
/static/3a1b4c6e74adfd5afaaa323f54c4c699/40601/no-mystery.png 945w,
/static/3a1b4c6e74adfd5afaaa323f54c4c699/78612/no-mystery.png 1260w,
/static/3a1b4c6e74adfd5afaaa323f54c4c699/f02b9/no-mystery.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Also remember that before we said that positioned elements appear on top of
non-positioned elements? Well, now we can generalize by saying that
elements that form a stacking context appear on top of non-positioned
elements.&lt;/p&gt;
&lt;h2 id=&quot;the-usual-suspects&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-usual-suspects&quot; aria-label=&quot;the usual suspects permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The usual suspects&lt;/h2&gt;
&lt;p&gt;The
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context&quot;&gt;MDN article&lt;/a&gt;
lists all cases when a new stacking context is formed. I’m going to go through a
list of usual suspects.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://z-index.juliu.is/?css=p%2Bopacity%3A%200.90&quot;&gt;Opacity less than 1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3809618b7219c0eb8aea13f481174227/f02b9/opacity.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAADt0lEQVR42o2US0xcVQCGZ2viog+BGZhh7h0apwyFAUN5Kp2BSJkHMMx0hHnxbHmWtESQ0gqJiSVtZSBBaiIkNGUBCyOPaLRWXahIKW6aEFhIAHdsXBAIhofwmXtxwGZM6Em+/DmL891z7vlzFFqtFpVKJaNUKomKipIzIiICQRDIzc3F4SjBZrdQ4izmQqKBGE00WkFDrKBGK8Si0+kQRVFGkZiYSGlpKXa7HavVSnFx8RFFRUU4nU7MZjMJ+hRSErIwGtIxxh+SbMjAoE9GFAVZKqFwu93s7Oywu7vLwcEB/zeefv8ES2odjfZ+agoecLXgE2ou36fB1k9hdi0abQxxurhDodfr5aTx8y8/kf9WNXW2IJX5H1OV3y3nNUsPtswaWagLCVNTU2lpaaGpqSmMxsZGbty4SYnTQXFWE7WWIFX5d6m+3C2nNLdlXUUjqI+FeXl5TE5OMjY2Fsbo6CgT4xPc+fA29vR6aq2HwsMd/ivMqCJWHXks9Pv9Jx75+dws+SnV1Nn7qLZ0U2PpptpyV/6A9VIzakMSurhz6KRblm53cXGRhYWFMObn51ld/YPBoc+xXayjvvgzGlw9NF+5z3X3A5qLghRUjRHR+gW6Nw3oBC0Ko9FIZWUlDodDrkooQ0i1MZnNXNBdILnkDjdHfXR9mUHXeCZ53UFiO54TfWsSUZ9wKJRqs7+/z97enlwdKUNsb2/LR/72yXdEnHoNlauFj2bszL2IY/aFnodfXSO2+xmqtgniQsJXqc3Ms1lUp18n0nEb/6MhmEuDuSz+mrlEUs9TTrd+jaCPR5SEaWlpdHZ20t7eTmtrK21tbUdI846ODjw+P4LqLGcKb2H9dAKm0+HXTP788V0y7n2D8P44SYZEzokCCpPJJFdkeHiYwcFBhoaGjpDmIyMjtH3QjjbiFGdLuyi89wPUuzhoLGOvwctK5XV+DzSx6nwPR2ISCp/Pd+KR5+Z+Q/nGGaIu5uK0VYG7nH13hZyUeqHMB75KvMkpKKQHYGVlheXl5TCWlpZYW1tj5PFjYlTRqDQxuOP14KvgwBOQ2feU87enHDzllBmTD2vj8XheqkpYbUwmdIJAlCDgNqaAt4L9sgAH/+FI6HK52NraYnNzk42NDTlDrK+vyy/Q1NQU0UolKlHkSpJRXrxb6mevLHDEkfBVajM9PY0yMhKlKMqLCNSAv+plAtX4pX+YnZ1NX18fvb29YQSDQQYGBuSXR6NWoxFF3j4fz8McM/3vmOjPOWYgx0zO+Xj+AQaXrhAS52nXAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;opacity&quot;
        title=&quot;&quot;
        src=&quot;/static/3809618b7219c0eb8aea13f481174227/f058b/opacity.png&quot;
        srcset=&quot;/static/3809618b7219c0eb8aea13f481174227/c26ae/opacity.png 158w,
/static/3809618b7219c0eb8aea13f481174227/6bdcf/opacity.png 315w,
/static/3809618b7219c0eb8aea13f481174227/f058b/opacity.png 630w,
/static/3809618b7219c0eb8aea13f481174227/40601/opacity.png 945w,
/static/3809618b7219c0eb8aea13f481174227/78612/opacity.png 1260w,
/static/3809618b7219c0eb8aea13f481174227/f02b9/opacity.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://z-index.juliu.is/?css=p%2Btransform%3A%20rotate(30deg)&quot;&gt;Transform and filter effects&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2efb5e9bce68c348867bb8a7ba089794/f02b9/transform.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAADyElEQVR42o2UXUybZRiGe+6BAgItpfT72pkOlJYprDoGljKEFFq6QoH+8acJUCg/EYZoMIvLDDECgcGYoEw4kOmBA2N0UVyWSDbcTjQEDiQgZ5x4QCAQfiyX6ddRt2DC3uTK/T4H753neXLnlanVahQKRYSEhARJY2NjEQQBs9mM3W7HarVSWurkvDGXRJUStZiEVqNFo9EgiqKkIWR6vZ6ysjIsFgv5+fnk5eVRUFBAcXExNpsNh8OB2ZyLKkmJUW+myTrMxawmXtG9ikqdgCgKaDTaiKksZLa/v8/e3p6kOzs7kj55ZmdniYuLw5fXTcB6g4DtBnWWPvKNXl7S6khSKyOdytxuNyedu/d+Jl13gVb759QXDkj4i4Zoto1Sk/8x59IKEAR1uMP09HTa2tpobGzE7/dLhO7hupHmlgBVvlqqLlyhyXqdhsJB/EXXJK2z9NNqH+cto/dxl1pkubm5TE9PMzU19b/c+vorWrw91BcM01A0IJn5CwdpKBygyTqCL+d9NOqkx7vUIPN6vSeO/OM387iyLtNm+wx/aFzrgGQesF7H+EY5iSmpaLSnwjssKipiaWmJxcXFYywsLLC2tsbNiS8QlBpslg+ot43SkDdCS8EgDvcE8Zfvomy7hahLQSOokRkMBqqrq6WshaJypEeEYmPKMaOSx6B0BAhM1dLc2Epd8Se8duVLoq7+jvLSNKLu5bCh0+kkGAxycHAgxSWkR+zu7oZHvnMHefTzqEra+eiBhfnfkrn3XQ4j0+8gXp1D0XEb7ZHhs8Tm/oN5FFHPEXuxC+/NMXiUAX9ksHP/TVI//Ymo9u8RdMmIIcOzZ8/S3d1NZ2cn7e3tdHR0RAjVXV1duDxeBEUM0db3sFy7Db8aYe4cf/+Sx+s9PyC8+y36lFROiQIyk8kkxWN8fJzR0VHGxsYihOrJyUk6LnWijn2BmPIPsfbMQn0Jh/4KDhrcrFY38aevkb8cZdhT9cg8Hs+JIz98+Aj5i9HEZ5hxFNaAs5Kgs0pSyt1Q4QFPNe60M8hCH8Dq6iorKyvHWF5eZn19ncmJCZSKBBQqJc5kHXiqOHT5JIKuSv5xVYKrkgpDWjg2Lpfrqagci43JhEYQiBcEnIYz4K4iWOHj8AkihiUlJWxvb7O1tcXm5qakR2xsbHB4eMjMzAwJcjkKUaRUb5Ae75d7OajwRYgYPkts5ubmkMfFIRdF6RG+t8Fb8zS+WryhHWZmZtLf309fX98xent7GRoakn4eVWIiKlHk/OlkhrNzGMwyMZj9H0PZOWSfTuZfT92vr9Dq/RYAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;transform&quot;
        title=&quot;&quot;
        src=&quot;/static/2efb5e9bce68c348867bb8a7ba089794/f058b/transform.png&quot;
        srcset=&quot;/static/2efb5e9bce68c348867bb8a7ba089794/c26ae/transform.png 158w,
/static/2efb5e9bce68c348867bb8a7ba089794/6bdcf/transform.png 315w,
/static/2efb5e9bce68c348867bb8a7ba089794/f058b/transform.png 630w,
/static/2efb5e9bce68c348867bb8a7ba089794/40601/transform.png 945w,
/static/2efb5e9bce68c348867bb8a7ba089794/78612/transform.png 1260w,
/static/2efb5e9bce68c348867bb8a7ba089794/f02b9/transform.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bdisplay%3A%20flex%7Cp%2Bposition%3A%20relative%3Bz-index%3A%201%7Cy%2Bz-index%3A%202&quot;&gt;Flex child with z-index&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/bfc982cc7751b6f9c688330abbb6f131/f02b9/flex-child.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD0ElEQVR42o3UW0xbdQDH8T5qYlQMl3LtOUXlWjpuorABJcEILbS0ILQUqPNBoIyOmwQ3QV3MEsO1MBhtlIAJEGO2kGhgGhNRMhQfjEF4kAB7I+ILl5AQbl9zDgFX98D+ySf/cx7OL+f/P7/zV6hUKpRKpSw4OFgmXQcEBCAIAjk5OZhMReTr8zCZC4nXxBIaFoxKCCdCFYZKiECtViOKokyh0WgoLS3FYDCQm5tLXl4eRqNRVlhYiNlsRqfTER+VTHL8ZRLj0kmMfUOWFJdBfFQigijIoRJFcXExm5ubbG9vs7+/z9HREf8fD76bwfj6dRrNI9QVDHKtYAhnwSCNphEsmS7CVSFEqiNPA202GxeNn37+EcNrTlwmD9X6Xmr0fVTn91JfOIzpitM3MCUlhcbGRurq6nA6nT5qa2txua5TZDZSktksB0hhtQY31fo+XEYPliwnghgqB4qiGoW0PyMjIwwPD8vz5OQkExMTsvHxce7fu8+Nmx9gzmig3uiRA2sMbmr0vdQZPic3xYVfoBL12Rva7fYLl/zrwjyGVGnJXmoMfTgL+rj65iCd1R+zNJnL+G0tcdGRqAQRhfR1l5eXZUtLSz4WFxdZX3+Ex3uXovQGGoxeqt/qpzb/Dg7dMN6WJlhL5p/vM9DGRxKhElFotVocDgcmk0muytl8RqpNtk6HJjKBpKKbNHxZSde9JLI+6cfV2Q/LMfz9bSLaOPVpYElJCcfHxxweHnJwcCDPZ6QaSWN65gH+LzxLqKWRpod6hv58kfQvOkn9bBrP12103GkiJiZK/hGeqjYP538hyO95REszsX3fkNAzinB7Br+OeZ756A+ea5om4tU4REGFIi0tjfb2dlpbW2lubqalpeWcdN/W1oa13E6E0p/wogaCbv2O6sYc6vZZXun4gahbs0S1fEV8rIaXRQFFVlYWQ0NDuN1uvF6vD4/Hw9jYGC3vtxIR4Id/2YfkfjrLo4r3+Kvqmmylqp6VilrWzW9j0iSgKC8vv3DJCwu/ofR/iaDUHIr1Dii1QqntMeVQ7sB2KRGFdACsra3JVldXfaysrLCxscHY6CihwSEEh4dSEhMFNgdH1kofWCsp0146rY3VavWpyhO1yc5GLQgECQIl2kSwVXFcVsHJY84DLRYLe3t77O7usrOzI89ntra2ODk5YWpqihDpvBRFihO08sMHpXYOyyrOnQc+TW3m5uZQBgaiFEX5ISreBfs7viquYpf2MCMjg56eHrq7u5/Q1dXFwMCAfPKEh4URLopcjo7hTqYO95Vs3Jn/GcjUkRkdw78L5LA0DNcsuAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;flex child&quot;
        title=&quot;&quot;
        src=&quot;/static/bfc982cc7751b6f9c688330abbb6f131/f058b/flex-child.png&quot;
        srcset=&quot;/static/bfc982cc7751b6f9c688330abbb6f131/c26ae/flex-child.png 158w,
/static/bfc982cc7751b6f9c688330abbb6f131/6bdcf/flex-child.png 315w,
/static/bfc982cc7751b6f9c688330abbb6f131/f058b/flex-child.png 630w,
/static/bfc982cc7751b6f9c688330abbb6f131/40601/flex-child.png 945w,
/static/bfc982cc7751b6f9c688330abbb6f131/78612/flex-child.png 1260w,
/static/bfc982cc7751b6f9c688330abbb6f131/f02b9/flex-child.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://z-index.juliu.is/?css=b%2Bdisplay%3A%20grid%7Cg%2Bz-index%3A%202%7Cp%2Bposition%3A%20relative%3Bz-index%3A%201&quot;&gt;Grid child with z-index&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/7b9b78fe695e1dcf2c857e801b593b9b/f02b9/grid-child.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 97.46835443037975%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAABYlAAAWJQFJUiTwAAAD4ElEQVR42o2Ua0ibVxjH83Uw2HrRGjW+7xvLvNREbZ3YaSVxyKom5qJpEhPFbbAaY71k0dVOYZcyVoaXlrRbY9VVhrKx1Qmja1cYW+vqtN2+iCgTdZ/mcB8mili8/cb7FhXXD+2BH+ecD+cHz3P+PCpBEIiKilJQq9UK8jkiIgJRFMnLy8NqtVFYVIDVXkyKLpmYWDWCqCFOiEUQ49BqtUiSpKDS6XQ4nU5MJhP5+fkUFBRgsVgUiouLsdvtGI1GUhKOcSwlh/Qjr5CefFzh6JFsUhLSESVRkcqoSktLWVhYYHFxkdXVVTY2Nvj/uv3DLSxZ9QTsvdSYr3DG/Cl+8xUC1l5KcuvQCNHEa+MfC8vKynjaunvvJ0yZfuqsYaqKOvEVXaSqsJPa4qtYT/j3CjMyMggEAtTU1OD3+/dQXV1NXV09NrsFR25QEfhMF6k2XcJn6qTOEsZ2ogaNELMrlPvT29tLOBymu7ubgYGBHfr7+xm8Mci7LeewZzdQawlTdTKE7+QVTr8WotZ8DVuOD01s5K7Q6/U+teTRsRFML8sld1Hj+oha73nOeD6kvjSE1RgkNllHfPxhtPIvy787NTXF5OQkExMTexgfH2du7k/CXZ9hO95Ag6WLD77O4cL9RD4eSaQ1+BZm15dENH2F9qVktKKASq/X43K5KCwsxGq17kRmGzk2BqMRXbyeo7YWzv6YT9vDONp+EzBdfB+haZTo5m+REo48FjocDpaWllheXmZ9fZ21tTVll3n06JFS8ve3bnPwheeIKQnw9s/FdIwKtI9JOL9oIfL878Q0foN2W/gssbk/8ivqfc9zyHaOU59f5Z/RdP4ey+Cvewb0n9xhX/A7xIQkJFmYmZlJa2srTU1NBINBGhsbd5Dvzc3NuD1eJPUB9pvPYro8CA8y4WEW//7yKlkXbiIGbqBP1nFYElEZDAYlIj09PUp0urq6dpDvfX19NDa9gxD5IgdK3sN87SbczWRzOJv1OwZmfT7+8PiZs5/CqtOj8ng8Ty15bOwBUQf3cygjD7ulEqpcbFa54bQb3GXg9ICnkrK0dFTyAJidnWVmZuYJpqenmZ+fp+/6dWLU0ag1MTgSE8BZyZajQmHTVcGGuwLcFbhS01ClpqbidrufiMue2BgMaEWRQ6KIIy0dyirYdJeztY2rfFdYUlLCysqKEpvt+GwjT6CtrS2GhoaIluelJFGqT1Uerzm9rLvKd9gRPktshoeHiYqMJEqSlEeUvwne1/dS/gZeuYfZ2dl0dHTQ3t7+BG1tbYRCIWXyaGJj0UgSOYlJXM41cumEgUu5u4RyjeQmJvEf2aiwwEh6aeQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;grid child&quot;
        title=&quot;&quot;
        src=&quot;/static/7b9b78fe695e1dcf2c857e801b593b9b/f058b/grid-child.png&quot;
        srcset=&quot;/static/7b9b78fe695e1dcf2c857e801b593b9b/c26ae/grid-child.png 158w,
/static/7b9b78fe695e1dcf2c857e801b593b9b/6bdcf/grid-child.png 315w,
/static/7b9b78fe695e1dcf2c857e801b593b9b/f058b/grid-child.png 630w,
/static/7b9b78fe695e1dcf2c857e801b593b9b/40601/grid-child.png 945w,
/static/7b9b78fe695e1dcf2c857e801b593b9b/78612/grid-child.png 1260w,
/static/7b9b78fe695e1dcf2c857e801b593b9b/f02b9/grid-child.png 1554w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Some of these examples might look surprising. In general, the underlying
reason why these configurations create a new stacking context is that they
render to an offscreen context. But in practice, you don’t need to remember
all of them: when you bump into a situation where &lt;code class=&quot;language-text&quot;&gt;z-index&lt;/code&gt; isn’t working
as intended, you can quickly check if there’s a runaway stacking context
that’s keeping you locked up.&lt;/p&gt;
&lt;p&gt;I recommend going through each one of the examples, playing around with
them, and explaining in your head why they make perfect sense. It might be
helpful to install a browser extension to help check your intuition and
solidify your understanding
(&lt;a href=&quot;https://chrome.google.com/webstore/detail/z-context/jigamimbjojkdgnlldajknogfgncplbh&quot;&gt;Chrome&lt;/a&gt;,
&lt;a href=&quot;https://addons.mozilla.org/en-GB/firefox/addon/devtools-z-index/&quot;&gt;Firefox&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;That’s all I have for you today. As always, thanks for reading!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Permutate parsers, don't validate]]></title><description><![CDATA[“Parse, don’t
validate”
has been one of my favourite programming articles for some time. The main
gist of the article is that, when writing…]]></description><link>https://juliu.is/permutate-parsers/</link><guid isPermaLink="false">https://juliu.is/permutate-parsers/</guid><pubDate>Wed, 13 Jan 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/&quot;&gt;“Parse, don’t
validate”&lt;/a&gt;
has been one of my favourite programming articles for some time. The main
gist of the article is that, when writing in a type-driven fashion, your
snappy slogan should be:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Parse, don’t validate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The core difference between parsing and validating can be explained by
looking at two very similar functions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;parseInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;parseInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Read&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;readMaybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;validateInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;validateInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Read&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;readMaybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;str&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, they look very similar. The main difference is that
&lt;code class=&quot;language-text&quot;&gt;parseInt&lt;/code&gt; returns a useful value, the &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt; that we wanted to parse, while
&lt;code class=&quot;language-text&quot;&gt;validateInt&lt;/code&gt; takes that useful value and throws it away. This is also
mentioned in the wonderful &lt;a href=&quot;https://kowainik.github.io/posts/haskell-mini-patterns#evidence&quot;&gt;Haskell Mini-Patterns
Handbook&lt;/a&gt;
as the “Evidence” pattern.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The key issue here is that by calling a function that returns Bool you
lose the information about earlier performed validation. Instead, you can
keep this information by explicitly pattern-matching on the validation or
result.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In this post, I would like to go through a practical example that shows the
power of bringing this concept to its limits. Which brings us to…&lt;/p&gt;
&lt;h2 id=&quot;advent-of-code-2020-day-4&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#advent-of-code-2020-day-4&quot; aria-label=&quot;advent of code 2020 day 4 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Advent of Code 2020, Day 4&lt;/h2&gt;
&lt;p&gt;We &lt;a href=&quot;https://adventofcode.com/2020/day/4&quot;&gt;are tasked&lt;/a&gt; with parsing a batch
of passports composed of these fields:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;- byr (Birth Year)
- iyr (Issue Year)
- eyr (Expiration Year)
- hgt (Height)
- hcl (Hair Color)
- ecl (Eye Color)
- pid (Passport ID)
- cid (Country ID)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All the fields are required except for the &lt;code class=&quot;language-text&quot;&gt;cid&lt;/code&gt; field, which is optional.
Note that the fields can be written in any order, this will be important
later. Our batch is composed of multiple passports separated by empty lines
(the &lt;code class=&quot;language-text&quot;&gt;input.txt&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;ecl:gry pid:860033327 eyr:2020 hcl:#fffffd
byr:1937 iyr:2017 cid:147 hgt:183cm

iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884
hcl:#cfa07d byr:1929

hcl:#ae17e1 iyr:2013
eyr:2024
ecl:brn pid:760753108 byr:1931
hgt:179cm

hcl:#cfa07d eyr:2025 pid:166559648
iyr:2011 ecl:brn hgt:59in&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;The first passport is &lt;em&gt;valid&lt;/em&gt; - all required fields are present.&lt;/li&gt;
&lt;li&gt;The second passport is &lt;em&gt;invalid&lt;/em&gt; - it is missing &lt;code class=&quot;language-text&quot;&gt;hgt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The third passport is interesting: the only missing field is the optional &lt;code class=&quot;language-text&quot;&gt;cid&lt;/code&gt;, which makes it &lt;em&gt;valid&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The fourth passport is missing two fields, &lt;code class=&quot;language-text&quot;&gt;cid&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;byr&lt;/code&gt;. Missing &lt;code class=&quot;language-text&quot;&gt;cid&lt;/code&gt; is fine, but missing &lt;code class=&quot;language-text&quot;&gt;byr&lt;/code&gt; is not, so this passport is &lt;em&gt;invalid&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The challenge is to count &lt;strong&gt;how many passports&lt;/strong&gt; are &lt;strong&gt;valid&lt;/strong&gt; in the given
batch.&lt;/p&gt;
&lt;p&gt;Let’s write some code to open the file and parse each group of passport
fields:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;

&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;qualified&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;List&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Split &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; S&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;input.txt&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entries&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;parseEntry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;S&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;splitOn&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entries&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;parseEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;parseEntry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nothing too fancy here, we’re using &lt;code class=&quot;language-text&quot;&gt;Data.List.Split&lt;/code&gt; from the &lt;code class=&quot;language-text&quot;&gt;split&lt;/code&gt;
package to do the heavy lifting. And the implementation of &lt;code class=&quot;language-text&quot;&gt;parseEntry&lt;/code&gt; has
been conveniently stubbed so that the code compiles.&lt;/p&gt;
&lt;p&gt;Now how should our &lt;code class=&quot;language-text&quot;&gt;PassportEntry&lt;/code&gt; data structure look like? I’d love to
eventually represent passports as:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;birthYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;issueYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;expirationYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;hairColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;eyeColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;passportId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;countryId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we imagine parsing each field sequentially, we can see that we won’t be
able to construct this data structure in a single operation. We’ll have to
accumulate the data up until we’re ready to create a proper &lt;code class=&quot;language-text&quot;&gt;Passport&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One way to store the fields is to insert them into a hash. First of all,
we’re going to use a custom data type to represent the keys of the hash.
Why is that? We really don’t want to be making typos later when comparing
raw strings like &lt;code class=&quot;language-text&quot;&gt;&quot;ecl&quot;&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;&quot;elc&quot;&lt;/code&gt;. We’ll use a &lt;code class=&quot;language-text&quot;&gt;HashMap&lt;/code&gt; from the
&lt;code class=&quot;language-text&quot;&gt;Data.HashMap.Strict&lt;/code&gt; module:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;qualified&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HashMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Strict &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HM&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HM&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HashMap&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course things can’t be that easy. We also need to make our type
implement the &lt;code class=&quot;language-text&quot;&gt;Hashable&lt;/code&gt; typeclass:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-# LANGUAGE DeriveGeneric #-}&lt;/span&gt;

&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;qualified&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HashMap&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Strict &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; HM&lt;/span&gt;
&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Hashable&lt;/span&gt;
&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; GHC&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Generics&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Generic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Generic&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;instance&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Hashable&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HM&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;HashMap&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Don’t worry about what we’ve added. Just take them as God-given truths. 👼&lt;/p&gt;
&lt;p&gt;Okay, now we can implement our &lt;code class=&quot;language-text&quot;&gt;parseEntry&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;mapMaybe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;qualified&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Char &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; Char&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;parseEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;parseEntry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;HM&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fromList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;mapMaybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;parseTag&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
      &lt;span class=&quot;token hvariable&quot;&gt;S&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;splitWhen&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;isSpace&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;line&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;parseTag&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;parseTag&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;S&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;splitOn&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;:&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;byr&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;byr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;byr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;iyr&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;iyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;iyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;eyr&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hgt&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hcl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ecl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;pid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;cid&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We try to parse each field (such as &lt;code class=&quot;language-text&quot;&gt;byr:2002&lt;/code&gt;) into a &lt;code class=&quot;language-text&quot;&gt;PassportField&lt;/code&gt;
type, then end up building a hash using &lt;code class=&quot;language-text&quot;&gt;HM.fromList&lt;/code&gt;. We can take this for
a spin:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;l&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Main&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hs&lt;/span&gt;

&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;fromList&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;147&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1937&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2017&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#fffffd&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2020&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;183cm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;860033327&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;fromList&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;350&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1929&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2013&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#cfa07d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2023&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;amb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;028048884&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;fromList&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1931&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2013&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#ae17e1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2024&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;brn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;179cm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;760753108&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;fromList&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2011&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;#cfa07d&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2025&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;brn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;59in&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;166559648&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Nice and tidy! 🦾&lt;/p&gt;
&lt;p&gt;Now our goal is to verify which one of these groups is valid. First of all,
we should define a list of required fields:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;requiredFields&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;requiredFields&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can then define a validation function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isEntryValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isEntryValid&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;`HM.member`&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;requiredFields&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And change our main function to use that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;input.txt&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entries&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;parseEntry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;S&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;splitOn&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isEntryValid&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entries&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running this yields &lt;code class=&quot;language-text&quot;&gt;2&lt;/code&gt;, which is the correct answer!
&lt;a href=&quot;https://gist.github.com/Arkham/b749043e1622bf01c96eefe303df0b9b&quot;&gt;Here&lt;/a&gt; is
all the code we have written so far, if you’re feeling like you need a
refresher.&lt;/p&gt;
&lt;h2 id=&quot;advent-of-code-2020-day-4-part-ii&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#advent-of-code-2020-day-4-part-ii&quot; aria-label=&quot;advent of code 2020 day 4 part ii permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Advent of Code 2020, Day 4, Part II&lt;/h2&gt;
&lt;p&gt;In the second part of the challenge, these new rules are added:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;- byr (Birth Year) - four digits; between 1920 and 2002.
- iyr (Issue Year) - four digits; between 2010 and 2020.
- eyr (Expiration Year) - four digits; between 2020 and 2030.
- hgt (Height) - a number followed by either cm or in:
  - If cm, the number must be between 150 and 193.
  - If in, the number must be between 59 and 76.
- hcl (Hair Color) - a &apos;#&apos; followed by six chars 0-9 or a-f.
- ecl (Eye Color) - one of: amb blu brn gry grn hzl oth.
- pid (Passport ID) - a nine-digit number.
- cid (Country ID) - ignored, missing or not.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is a new batch for us to peruse:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
hcl:#623a2f

eyr:1972 cid:100
hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;the first passport is &lt;em&gt;valid&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;the second passport is &lt;em&gt;invalid&lt;/em&gt; (look at the &lt;code class=&quot;language-text&quot;&gt;eyr&lt;/code&gt; field)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These new requirements are a bit annoying. Our simple approach of checking
if all required fields are present won’t work any longer. We can instead
implement a &lt;code class=&quot;language-text&quot;&gt;isFieldValid&lt;/code&gt; function to check if all fields are valid.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isFieldValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isFieldValid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;BirthYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
       &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1920&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2002&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;IssueYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
       &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2010&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;ExpirationYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
       &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2030&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;isDigit&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cm&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;num&lt;/span&gt;
           &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;193&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;in&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;num&lt;/span&gt;
           &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;76&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
          &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;HairColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;#&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;rest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
          &lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;`elem`&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;allowedHexChars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;rest&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
          &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;EyeColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;`elem`&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;validEyeColors&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;PassportId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;isDigit&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;isDigit&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;validEyeColors&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;validEyeColors&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;amb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;blu&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;brn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;grn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hzl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;oth&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;allowedHexChars&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Char&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;allowedHexChars&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token char string&quot;&gt;&apos;0&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;9&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token char string&quot;&gt;&apos;a&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;f&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then we can change our &lt;code class=&quot;language-text&quot;&gt;isEntryValid&lt;/code&gt; to use this function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isEntryValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isEntryValid&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;requiredFieldsPresent&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;allFieldsValid&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;requiredFieldsPresent&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;`HM.member`&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;requiredFields&lt;/span&gt;

    &lt;span class=&quot;token hvariable&quot;&gt;allFieldsValid&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isFieldValid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;HM&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;toList&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running this program on our second data sample yields &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;, and it will be
good enough to solve the Advent of Code challenge and get us those sweet
sweet stars.&lt;/p&gt;
&lt;p&gt;🎉 🎉 🎉&lt;/p&gt;
&lt;h2 id=&quot;a-moment-of-reflection&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-moment-of-reflection&quot; aria-label=&quot;a moment of reflection permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A moment of reflection&lt;/h2&gt;
&lt;p&gt;If we look back at the &lt;a href=&quot;https://gist.github.com/Arkham/923df6e872d855101bca4261f7d71e65&quot;&gt;current
state&lt;/a&gt; of
our code, we can see that we are doing a lot of validations.&lt;/p&gt;
&lt;p&gt;We do a lot of work to verify if something is valid, then throw it all out
of the window to return a meagre &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;. German folks from the &lt;a href=&quot;https://en.wikipedia.org/wiki/Don%27t_throw_the_baby_out_with_the_bathwater&quot;&gt;sixteenth
century&lt;/a&gt;
would have told us snarkily:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;das Kind mit dem Bade ausschütten&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yes, literally &lt;em&gt;throwing the baby out with the bathwater&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This would be even more true if we were given a new challenge:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now find the unique set of eye colors in all valid passports&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With our current code, we know which passport is valid, but we have no way
of extracting the eye color of a valid passport. This is why earlier we
were mentioning this sort of &lt;code class=&quot;language-text&quot;&gt;Passport&lt;/code&gt; representation:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;birthYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;issueYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;expirationYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;hairColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;eyeColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;passportId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;countryId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we had a function like &lt;code class=&quot;language-text&quot;&gt;parsePassport&lt;/code&gt; that went from &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Maybe
Passport&lt;/code&gt; we could then write some code like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;Set&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;fromList&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyeColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;mapMaybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;parsePassport&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;S&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;splitOn&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But let’s not get too ahead of ourselves. Let’s try to refactor our current
code to do something similar. First we can try to write a function like
this one:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;entryToPassport&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This function takes the intermediate representation of a collection of
passport fields and returns a ‘validated’ passport. We can also reuse our
&lt;code class=&quot;language-text&quot;&gt;isFieldValid&lt;/code&gt; function by using this trick:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;parseField&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;PassportField&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;parseField&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tuple&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isFieldValid&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tuple&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;tuple&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We are still reusing the validating logic, but we end up returning
something useful instead. Remember, we are slowly migrating our code from
validating data to parsing data.&lt;/p&gt;
&lt;p&gt;Using our new helper we can finally implement the &lt;code class=&quot;language-text&quot;&gt;entryToPassport&lt;/code&gt;
function. We’ll do that in two separate steps. First we’ll get all the
values of the required fields:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;getAllRequiredFields&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;getAllRequiredFields&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;traverse&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;\&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;lookup&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;field&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;e&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;_field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;parseField&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;requiredFields&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;traverse&lt;/code&gt; magic ensures that we either get all the values we’re
looking for wrapped in a &lt;code class=&quot;language-text&quot;&gt;Just&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;Nothing&lt;/code&gt; if any of those fields were
invalid. Ok, we’re ready to roll now!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;entryToPassport&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PassportEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;entryToPassport&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;getAllRequiredFields&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;byr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;iyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;hgt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;hcl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;ecl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;birthYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;byr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;issueYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;iyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;expirationYear&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;height&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;hgt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;hairColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;hcl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;eyeColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;ecl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;passportId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;countryId&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;$&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;HM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;lookup&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CountryId&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We end up having to pass &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt; values around, which need to be parsed
again into the exact types that we desire. Also we need to pass these
values into a list and hope not to mess up the ordering of the fields. So
it’s far from perfect, but we’re getting somewhere.&lt;/p&gt;
&lt;p&gt;In order to use this function in our main, we replace the last line of the
main fuction from:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isEntryValid&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entries&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;mapMaybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entryToPassport&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entries&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Running
&lt;a href=&quot;https://gist.github.com/Arkham/22cb983c61f5a6aaf54227c94d0c7a6b&quot;&gt;this&lt;/a&gt; on
our test batch still returns &lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;, which is a good sign we haven’t broken
anything.&lt;/p&gt;
&lt;p&gt;Still, there is one thing that I’m particularly unhappy about in this code:
we use an intermediate representation of the passport that has no real
domain value. Nobody cares about &lt;code class=&quot;language-text&quot;&gt;PassportField&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;PassportEntry&lt;/code&gt;, but
we need to have these types in order to build our &lt;code class=&quot;language-text&quot;&gt;Passport&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Not only that, but having these intermediate types means that there are
bugs waiting to happen when we transform them to our desired data type:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;getting the order of the fields wrong&lt;/li&gt;
&lt;li&gt;parsing strings in inconsistent ways&lt;/li&gt;
&lt;li&gt;forgetting to validate the presence of required fields&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is also known as &lt;em&gt;shotgun parsing&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Shotgun parsing is a programming antipattern whereby parsing and input-validating code is mixed with and spread across processing code—throwing a cloud of checks at the input, and hoping, without any systematic justification, that one or another would catch all the “bad” cases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In “Parse, don’t validate”, Alexis King goes on to describe how this is
specifically related to parsing and validating:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It may not be immediately apparent what shotgun parsing has to do with validation—after all, if you do all your validation up front, you mitigate the risk of shotgun parsing. The problem is that validation-based approaches make it extremely difficult or impossible to determine if everything was actually validated up front or if some of those so-called “impossible” cases might actually happen. The entire program must assume that raising an exception anywhere is not only possible, it’s regularly necessary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;How can we avoid doing this? Let’s try something new!&lt;/p&gt;
&lt;h2 id=&quot;a-new-perspective&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-new-perspective&quot; aria-label=&quot;a new perspective permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A new perspective&lt;/h2&gt;
&lt;p&gt;We’re going to write the same program using
&lt;a href=&quot;https://hackage.haskell.org/package/parsec&quot;&gt;parsec&lt;/a&gt;, a monadic parser
combinator library. I’ve recently bumped
into this excellent &lt;a href=&quot;https://hasura.io/blog/parser-combinators-walkthrough/&quot;&gt;walkthrough to parser
combinators&lt;/a&gt;, which
I thouroughly recommend reading.&lt;/p&gt;
&lt;p&gt;In short a parser is a type like this one:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;runParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;ParseError&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It works by consuming input characters from the input string and returning
a tuple with two values:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The first value is what’s left of the input string, so that other
parsers can keep parsing the rest of the input.&lt;/li&gt;
&lt;li&gt;The second value contains either a parse error or a properly parsed value of type &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We’ll need to install &lt;code class=&quot;language-text&quot;&gt;parsec&lt;/code&gt; and add some imports:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;qualified&lt;/span&gt; Text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Parsec &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; P&lt;/span&gt;
&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Parsec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;String&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Control&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Monad&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let’s implement parsers for some fields:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- byr (Birth Year) - four digits; between 1920 and 2002.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;byrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;byrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;byr&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1920&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2002&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- iyr (Issue Year) - four digits; between 2010 and 2020.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;iyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;iyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;iyr&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2010&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;-- eyr (Expiration Year) - four digits; between 2020 and 2030.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;eyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;eyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eyr&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2030&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we use the &lt;code class=&quot;language-text&quot;&gt;guard&lt;/code&gt; function to introduce an assertion that will make
the parser fail when the condition is not met. In general I feel that this
code is quite readable, but we might want to extract a reusable helper to
parse years:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;yearParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;yearParser&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;rangeStart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;rangeEnd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;rangeStart&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;rangeEnd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;int&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;byrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;byrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;yearParser&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;byr&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1920&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2002&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;iyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;iyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;yearParser&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;iyr&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2010&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;eyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;eyrParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;yearParser&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;eyr&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2030&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;🎉&lt;/p&gt;
&lt;p&gt;This is the beauty of writing parser combinators. They are &lt;strong&gt;extremely&lt;/strong&gt; easy to
reuse and combine.&lt;/p&gt;
&lt;p&gt;Now we want to write a parser for the height field. It might be nice to use
a more specialized data type to represent that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InCms&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;InInches&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Eq&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we go!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- hgt (Height) - a number followed by either cm or in:&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- If cm, the number must be between 150 and 193.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- If in, the number must be between 59 and 76.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;heightParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;heightParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hgt&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;digits&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;many1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;digits&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;unitParser&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;InCms&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;150&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;193&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;InInches&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
      &lt;span class=&quot;token hvariable&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;59&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;76&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;result&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s that &lt;code class=&quot;language-text&quot;&gt;unitParser&lt;/code&gt; you ask?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;unitParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Height&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;unitParser&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;cmParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cm&quot;&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;InCms&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;token hvariable&quot;&gt;inParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;in&quot;&lt;/span&gt;
        &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;InInches&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;choice&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;cmParser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;inParser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The rest of the parsers are basically a step by step translation of the
requirements in English:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- hcl (Hair Color) - a &apos;#&apos; followed by six chars 0-9 or a-f.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;hairColorParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;hairColorParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hcl&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;#&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;oneOf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0123456789abcdef&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- pid (Passport ID) - a nine-digit number.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;passportIdParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;passportIdParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;pid&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;count&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- cid (Country ID) - ignored, missing or not.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;countryIdParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;countryIdParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;cid&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;many1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;digit&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;value&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- ecl (Eye Color) - one of: amb blu brn gry grn hzl oth.&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;eyeColorParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;eyeColorParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ecl&quot;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;char&lt;/span&gt; &lt;span class=&quot;token char string&quot;&gt;&apos;:&apos;&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;choice&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;try&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;string&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;amb&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;blu&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;brn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;gry&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;grn&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;hzl&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;token string&quot;&gt;&quot;oth&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;spaces&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will notice we had to use this mysterious &lt;code class=&quot;language-text&quot;&gt;P.try&lt;/code&gt; function in the last
snippet. This is very useful when we need to look ahead in the input
string. Consider the example of &lt;code class=&quot;language-text&quot;&gt;blu&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;brn&lt;/code&gt;: after consuming an initial
&lt;code class=&quot;language-text&quot;&gt;b&lt;/code&gt; character we land in the &lt;code class=&quot;language-text&quot;&gt;blu&lt;/code&gt; branch. If at that point we encounter a
&lt;code class=&quot;language-text&quot;&gt;r&lt;/code&gt; character, we realize we need to go back and choose the &lt;code class=&quot;language-text&quot;&gt;brn&lt;/code&gt; branch
instead. But by default the parsing would stop because we have already
consumed the first character. &lt;code class=&quot;language-text&quot;&gt;P.try&lt;/code&gt; will make it so our parser pretends
it hasn’t consumed any input so that we can keep trying other
alternatives.&lt;/p&gt;
&lt;p&gt;We have now written parsers for each individual field. So now it’s time to
combine them all together…&lt;/p&gt;
&lt;h2 id=&quot;another-problem&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#another-problem&quot; aria-label=&quot;another problem permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Another problem?!&lt;/h2&gt;
&lt;p&gt;Remember that the fields can be written in any order? Uh oh.&lt;/p&gt;
&lt;p&gt;Since our parser tries to consume input one character at a time, how the
heck can we write one that has to deal with randomly ordered input?&lt;/p&gt;
&lt;p&gt;It is impossible, right?&lt;/p&gt;
&lt;p&gt;No, it’s &lt;strong&gt;possible&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;parsec&lt;/code&gt; library includes a wonderful &lt;code class=&quot;language-text&quot;&gt;Text.Parsec.Perm&lt;/code&gt; module:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This module implements permutation parsers. A permutation phrase is a
sequence of elements (possibly of different types) in which each element
occurs exactly once and the order is irrelevant. Some of the permutable
elements may be optional.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s import it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Text&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Parsec&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Perm&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;permute&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;$$&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;|?&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Woah, calm down, that’s lots of operators there mate.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;permute&lt;/code&gt; is the last call that will wrap everything up and return a
parser of something.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;$$&gt;&lt;/code&gt; is used to assign all the fields that we parsed to something. In
our case it will be a &lt;code class=&quot;language-text&quot;&gt;Passport&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;||&gt;&lt;/code&gt; is used to describe a required field&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;lt;|?&gt;&lt;/code&gt; is used to describe an optional field&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ready for the big reveal? 🥁🥁🥁&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;passportParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Parser&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;passportParser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;permute&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Passport&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;$$&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;byrParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;iyrParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;try&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyrParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;try&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;heightParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;try&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;hairColorParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;try&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;eyeColorParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;||&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;passportIdParser&lt;/span&gt;
      &lt;span class=&quot;token operator&quot;&gt;&amp;lt;|?&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;$&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;countryIdParser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This parser can parse passports which fields are written in any
random order, as long as each required field is present once. Pretty slick,
eh?&lt;/p&gt;
&lt;p&gt;We just need to wire it up in our main:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;IO&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;readFile&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;input.txt&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;passports&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;rights&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt;
          &lt;span class=&quot;token builtin&quot;&gt;map&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;P&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;parse&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;passportParser&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;S&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;splitOn&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;\n\n&quot;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;contents&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;passports&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That’s all we need! We can now get rid of the intermediate &lt;code class=&quot;language-text&quot;&gt;PassportField&lt;/code&gt;
and &lt;code class=&quot;language-text&quot;&gt;PassportEntry&lt;/code&gt; types and all that validation code. Welcome to the
wonderful world of parsing!&lt;/p&gt;
&lt;p&gt;If you glance over the &lt;a href=&quot;https://gist.github.com/Arkham/f3b76516b8a9c07cf2b0038871c60657&quot;&gt;final
listing&lt;/a&gt;
you’d be surprised to see how tidy it is. We have a description of the
input that we’d like to parse and nothing more. No validations, no
transformations, no other massaging of the types. That’s the beauty of
parsing and expressing real world problems in terms of parsing.&lt;/p&gt;
&lt;p&gt;I hope you enjoyed this deep dive into parsing, thanks for reading!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Complicated Haskell Words - Isomorphism]]></title><description><![CDATA[As someone who has been learning Haskell on and off for the last year, I
know the struggles of just how complicated Haskell can be for…]]></description><link>https://juliu.is/complicated-haskell-words-isomorphism/</link><guid isPermaLink="false">https://juliu.is/complicated-haskell-words-isomorphism/</guid><pubDate>Sun, 29 Nov 2020 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As someone who has been learning Haskell on and off for the last year, I
know the struggles of just how complicated Haskell can be for beginners.
You are instantly thrown off in a new world full of new terms, each one
more obscure than the other. Being familiar with a statically typed
language like &lt;a href=&quot;https://elm-lang.org&quot;&gt;Elm&lt;/a&gt; certainly helped, but I felt I
struggled the most with the seemingly endless list of new words I would
bump into every day… &lt;em&gt;Isomorphism&lt;/em&gt;, &lt;em&gt;functor&lt;/em&gt;, &lt;em&gt;monoid&lt;/em&gt;, &lt;em&gt;covariant&lt;/em&gt;,
and so on and so forth.&lt;/p&gt;
&lt;p&gt;So my goal here is to explain these terms using the simplest analogies I’ve
come across. Some of them might not be the most complete or the most
faithful, but my hope is that they will be useful lifeboats when you find
yourself lost at sea. I will try to keep this series updated over time by
adding new terms and simpler explanations. One word of warning: I won’t be
talking about monads since there are plenty of
&lt;a href=&quot;http://blog.sigfpe.com/2006/08/you-could-have-invented-monads-and.html&quot;&gt;tutorials&lt;/a&gt;
and &lt;a href=&quot;https://blog.plover.com/prog/burritos.html&quot;&gt;burritos&lt;/a&gt; out there.&lt;/p&gt;
&lt;h2 id=&quot;isomorphism&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#isomorphism&quot; aria-label=&quot;isomorphism permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Isomorphism&lt;/h2&gt;
&lt;p&gt;Let’s start with something that’s used all the time. If two things are
isomorphic, it means that &lt;em&gt;for all intents and purposes they are the same&lt;/em&gt;.
Anytime you read &lt;em&gt;isomorphic&lt;/em&gt;, just read &lt;em&gt;more or less the same for what we
care about&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This should be enough information for you to get on with your day. You can
close the tab now. Thanks for reading!&lt;/p&gt;
&lt;p&gt;The rest of this post is about building an intuitive understanding of why
isomorphisms are just &lt;em&gt;so damn cool&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let’s say we want to describe if we are happy or sad.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we could have a function that tells us if we are happy:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We could come up with a way to derive a &lt;code class=&quot;language-text&quot;&gt;Mood&lt;/code&gt; from a &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If we take a look at this pair of functions we can see that we can chain
them together.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;mysteriousFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;-- first run moodFromBool, then areWeHappy&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s try plugging some values to this mysterious function:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if we pass &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;, it gets converted to &lt;code class=&quot;language-text&quot;&gt;Happy&lt;/code&gt;, then back to &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if we pass &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt;, it gets converted to &lt;code class=&quot;language-text&quot;&gt;Sad&lt;/code&gt;, then back to &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So we basically implemented an identity function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This doesn’t sound too interesting, I know. What’s also not too interesting
is that there is another way to combine those two functions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;otherMysteriousFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;-- first run areWeHappy, then moodFromBool&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;if we pass &lt;code class=&quot;language-text&quot;&gt;Happy&lt;/code&gt;, it gets converted to &lt;code class=&quot;language-text&quot;&gt;True&lt;/code&gt;, then back to &lt;code class=&quot;language-text&quot;&gt;Happy&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if we pass &lt;code class=&quot;language-text&quot;&gt;Sad&lt;/code&gt;, it gets converted to &lt;code class=&quot;language-text&quot;&gt;False&lt;/code&gt;, then back to &lt;code class=&quot;language-text&quot;&gt;Sad&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another day, another identity function. What’s new?&lt;/p&gt;
&lt;h3 id=&quot;intermezzo-or-why-is-zero-cool&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#intermezzo-or-why-is-zero-cool&quot; aria-label=&quot;intermezzo or why is zero cool permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Intermezzo, or why is zero cool&lt;/h3&gt;
&lt;p&gt;The ancient Greeks were thoroughly confused by the number zero and used to wonder:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How can nothing be something?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Adding zero to an existing number is a no-op, it doesn’t do anything at
all. It’s a complete waste of effort!&lt;/p&gt;
&lt;p&gt;The great thing about zero is that it helps us to define a relationship
between numbers. The number &lt;code class=&quot;language-text&quot;&gt;3&lt;/code&gt; has now this beautiful property with
itself:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;none&quot;&gt;&lt;pre class=&quot;language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;3 - 3 = 0&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Not only that, without zero we wouldn’t even have negative numbers! Zero
stands as the legendary gatekeeper between positive and negative numbers.
Now each positive number &lt;code class=&quot;language-text&quot;&gt;a&lt;/code&gt; has a friend in the nether world &lt;code class=&quot;language-text&quot;&gt;a&apos;&lt;/code&gt;, which relation
is defined as:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&apos;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;back-to-identity-functions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#back-to-identity-functions&quot; aria-label=&quot;back to identity functions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Back to identity functions&lt;/h3&gt;
&lt;p&gt;That’s the same reason why identity functions are cool. They are a way to
establish &lt;em&gt;interesting relationships&lt;/em&gt; between other functions.&lt;/p&gt;
&lt;p&gt;Let’s do a quick refresher on the functions we had:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;mysteriousFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;mysteriousFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If our mysterious function is an identity function, it means we have
&lt;em&gt;successfully undone&lt;/em&gt; what &lt;code class=&quot;language-text&quot;&gt;moodFromBool&lt;/code&gt; did in the first place. We were
able to implement Control-Z for a function! We went from &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt; to
&lt;code class=&quot;language-text&quot;&gt;Mood&lt;/code&gt; and then back to &lt;code class=&quot;language-text&quot;&gt;Mood&lt;/code&gt; without losing any information.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;otherMysteriousFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;otherMysteriousFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;token hvariable&quot;&gt;moodFromBool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;areWeHappy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the other mysterious function, we were able to go from &lt;code class=&quot;language-text&quot;&gt;Mood&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;
and then back to &lt;code class=&quot;language-text&quot;&gt;Mood&lt;/code&gt; without losing information.&lt;/p&gt;
&lt;h3 id=&quot;the-definition&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-definition&quot; aria-label=&quot;the definition permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The definition™&lt;/h3&gt;
&lt;p&gt;Two types &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt; are isomorphic if two conversion functions exist such
that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;A&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And these two properties are valid:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Having this pair of functions means that we can losslessly convert between
values of type &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt; and values of type &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So this is what we meant at the beginning when we said that &lt;em&gt;for all
intents and purposes&lt;/em&gt; &lt;code class=&quot;language-text&quot;&gt;A&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;B&lt;/code&gt; are the same!&lt;/p&gt;
&lt;h3 id=&quot;many-isomorphisms&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#many-isomorphisms&quot; aria-label=&quot;many isomorphisms permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Many isomorphisms&lt;/h3&gt;
&lt;p&gt;Note that the multiple isomorphisms can exist between two types. For
example we could have this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;areWeSad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;areWeSad&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;areWeSad&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;moodFromBoolSad&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Mood&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;moodFromBoolSad&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sad&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;moodFromBoolSad&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Happy&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s the lesson here? All isomorphisms are born equal, and no isomorphism
is more equal than others.&lt;/p&gt;
&lt;h3 id=&quot;some-examples-of-isomorphisms&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-examples-of-isomorphisms&quot; aria-label=&quot;some examples of isomorphisms permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some examples of isomorphisms&lt;/h3&gt;
&lt;p&gt;We can easily prove that &lt;code class=&quot;language-text&quot;&gt;(a, b)&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;(b, a)&lt;/code&gt; are isomorphic by importing
the &lt;code class=&quot;language-text&quot;&gt;Data.Tuple&lt;/code&gt; module:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;swap&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;swap&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the same module, there’s another couple of functions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;uncurry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Those type signatures look quite funky, right? &lt;code class=&quot;language-text&quot;&gt;curry&lt;/code&gt; lets us apply a
function, originally intended to be used on a tuple, on two separate
arguments:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While &lt;code class=&quot;language-text&quot;&gt;uncurry&lt;/code&gt; lets us apply a function, originally intended to be used on
two arguments, on a tuple:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;uncurry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s prove that these functions create an isomorphism:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;uncurry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;curry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;uncurry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;After looking at the type signatures again we can say that these following
functions are isomorphic:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;c&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty neat!&lt;/p&gt;
&lt;h3 id=&quot;unit&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#unit&quot; aria-label=&quot;unit permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Unit&lt;/h3&gt;
&lt;p&gt;In Haskell you would sometimes see this type:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It’s an empty tuple, which is referred to as the &lt;em&gt;unit&lt;/em&gt;. It can contain a
single value, which can only be:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It turns out to be quite useful when you need a type that contains a single
value.&lt;/p&gt;
&lt;p&gt;For example, we could prove that &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Either () ()&lt;/code&gt; are isomorphic:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or that &lt;code class=&quot;language-text&quot;&gt;Maybe a&lt;/code&gt; is isomorphic to &lt;code class=&quot;language-text&quot;&gt;Either () a&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Either&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Maybe&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;g&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;one-more-thing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#one-more-thing&quot; aria-label=&quot;one more thing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;One more thing…&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Peano_axioms&quot;&gt;Peano numbers&lt;/a&gt; are a simple way of representing natural numbers using a zero value and a successor function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PeanoNum&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Zero&lt;/span&gt;
  &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PeanoNum&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;deriving&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can construct an isomorphism between this representation and &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;
(let’s just pretend for a moment that negative numbers aren’t a thing):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PeanoNum&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Zero&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;

&lt;span class=&quot;token builtin&quot;&gt;fromInt&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;PeanoNum&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fromInt&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Zero&lt;/span&gt;
&lt;span class=&quot;token builtin&quot;&gt;fromInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fromInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let’s take it for a spin:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Zero&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Zero&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;fromInt&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Succ&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Zero&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token constant&quot;&gt;Prelude&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;fromInt&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;🎉&lt;/p&gt;
&lt;p&gt;Thanks for reading, I hope you have emerged from this with a newfound sense
of awe for isomorphisms and identity functions!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A walkthrough of Elm Warrior]]></title><description><![CDATA[I’ve recently bumped into Elm
Warrior, an Elm adaptation of
Warrior JS. The premise of the game is to write a
simple AI that is able to…]]></description><link>https://juliu.is/elm-warrior-walkthrough/</link><guid isPermaLink="false">https://juliu.is/elm-warrior-walkthrough/</guid><pubDate>Fri, 09 Oct 2020 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve recently bumped into &lt;a href=&quot;https://github.com/Skinney/elm-warrior&quot;&gt;Elm
Warrior&lt;/a&gt;, an Elm adaptation of
&lt;a href=&quot;https://warriorjs.com/&quot;&gt;Warrior JS&lt;/a&gt;. The premise of the game is to write a
simple AI that is able to navigate through multiple levels of a dungeon.
This is how the first level looks like:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2ea920b259b52094fcc4f75eb7c3140d/236d7/level-one.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 59.49367088607595%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAABYlAAAWJQFJUiTwAAABl0lEQVR42pWQTWvbQBCG1+Cf10J7tXNLbnUSU3owjpy/UXooxORk6A8osSFtU3oKlqWV5DUrrYxtERsLZH1h74eypdpAGpem9DkNzDzMzAuSJKGUcs6FEIwxSqkQgnPOGOMlrER11RgtybIMqAYhxC9ZLpe+789ms8ViEQSB53lBEMznc9d1V6vVdDolhIRhKKVkjAHOeZ7nw+HQMAxd142S8XhsWZZpmo7jmKaJMYYQYowtyxqNRp7nPZF93yeETCYTCKHjOBhjwzAQQkmSpGmaZVme56pQPz7IlFIp5X2J/B8e5aIopJTdbvfo6PD09LjReNP4CwihfVkIIaWs1+sAgGq1Cv6gUqmoYjAYqGX78sFBDQDwtv35/Ufdtn9lY9u2OYI3t996dxevjl8AAL58vX5OfqddfbgwEBpDCBFCNnR+6N8/rS9fn7zcl3e7nZRSBVir1f55dr/fV8sopU8C6/V6zWZT65xrWud3tI6mnWvts3ar1XJd9zGw9Xodx/Fms4miaLvdFkUhniVN0yiK4jgOw/AnNEwniM2T2JkAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm Warrior level one&quot;
        title=&quot;&quot;
        src=&quot;/static/2ea920b259b52094fcc4f75eb7c3140d/f058b/level-one.png&quot;
        srcset=&quot;/static/2ea920b259b52094fcc4f75eb7c3140d/c26ae/level-one.png 158w,
/static/2ea920b259b52094fcc4f75eb7c3140d/6bdcf/level-one.png 315w,
/static/2ea920b259b52094fcc4f75eb7c3140d/f058b/level-one.png 630w,
/static/2ea920b259b52094fcc4f75eb7c3140d/40601/level-one.png 945w,
/static/2ea920b259b52094fcc4f75eb7c3140d/78612/level-one.png 1260w,
/static/2ea920b259b52094fcc4f75eb7c3140d/236d7/level-one.png 1486w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;You (the warrior) are represented by the &lt;code class=&quot;language-text&quot;&gt;@&lt;/code&gt;. You always start on the blue
tile and your goal is to reach the green tile. I thought it would be a cool
idea to write down how to approach solving a problem like this.&lt;/p&gt;
&lt;p&gt;Robin recently wrote a &lt;a href=&quot;https://dev.to/robinheghan/getting-started-with-elm-warrior-5b2n&quot;&gt;great
introduction&lt;/a&gt;
to how to play Elm Warrior and I wholeheartedly recommend reading it if
you’re just starting out.&lt;/p&gt;
&lt;p&gt;Before we begin, a word of warning…&lt;/p&gt;
&lt;h2 id=&quot;spoilers-ahead&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spoilers-ahead&quot; aria-label=&quot;spoilers ahead permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SPOILERS AHEAD!&lt;/h2&gt;
&lt;h2 id=&quot;spoilers-ahead-1&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spoilers-ahead-1&quot; aria-label=&quot;spoilers ahead 1 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SPOILERS AHEAD!!&lt;/h2&gt;
&lt;h2 id=&quot;spoilers-ahead-2&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#spoilers-ahead-2&quot; aria-label=&quot;spoilers ahead 2 permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;SPOILERS AHEAD!!!&lt;/h2&gt;
&lt;p&gt;Now that my conscience is clear, I’ll start by copying the exposed values
and functions from &lt;a href=&quot;https://package.elm-lang.org/packages/Skinney/elm-warrior/latest/&quot;&gt;each top-level
module&lt;/a&gt;
and pasting them all together in one file. No docs, no type signatures,
nothing, just their &lt;strong&gt;names&lt;/strong&gt;. As &lt;a href=&quot;https://cs.fit.edu/~ryan/rose.html&quot;&gt;the sage once
said&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Stat rosa pristina nomine, nomina nuda tenemus.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which roughly translates as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The rose of old remains only in its name. Only naked names we possess.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s get moving, shall we?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Action&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;position&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;health&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;maxHealth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;healingPotential&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;attackDamage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;inventory&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Coordinate&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Coordinate&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Direction&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.History&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;roundsPlayed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;previousStates&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;previousActions&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Item&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toString&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;look&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;lookDown&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Program&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;TurnFunction&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Config&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;program&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point we clearly don’t understand what is going on with the code,
but just by reading this listing a couple of times we are getting familiar
with the &lt;em&gt;names&lt;/em&gt; of this particular domain. Just let them soak in.&lt;/p&gt;
&lt;p&gt;Now I’m getting a tad more curious and will take a look at these exposed
data constructors: &lt;code class=&quot;language-text&quot;&gt;Direction&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Action&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;Item&lt;/code&gt;. Whenever a module
exposes the inner contents of a type, that’s an invitation to the world to
depend on those values, so I know it’s going to be useful to take a peek.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Up&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Action&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Wait&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Heal&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Pickup&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Move&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Attack&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Item&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Sword&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Potion&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is a lot of information packed in these simple names, so don’t worry
if you feel a bit overwhelmed. Instead, let’s try something practical and
look at the first level.&lt;/p&gt;
&lt;h2 id=&quot;level-i&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-i&quot; aria-label=&quot;level i permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level I&lt;/h2&gt;
&lt;p&gt;Let’s start &lt;a href=&quot;https://ellie-app.com/989KZm4BrVMa1&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The source on the left hand side reads like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Program&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Program.Model&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Program.Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Program.program&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;maps&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maps.all&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;players&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Player&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msPerTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;progressionFunction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Progression.reachExitPoint&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;


&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can see on the right hand side that every 500 ms a &lt;code class=&quot;language-text&quot;&gt;Player waits&lt;/code&gt;
message is being printed. So instead of simply waiting, we have to make our
warrior move to the right. Let’s import &lt;code class=&quot;language-text&quot;&gt;Direction&lt;/code&gt; and change the
&lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token import-statement&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; Warrior.Direction &lt;span class=&quot;token keyword&quot;&gt;exposing&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From now on I will provide Ellie links to each step, so don’t worry about
copying and pasting all the changes in the code.&lt;/p&gt;
&lt;p&gt;Onwards and upwards!&lt;/p&gt;
&lt;h2 id=&quot;level-ii&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-ii&quot; aria-label=&quot;level ii permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level II&lt;/h2&gt;
&lt;p&gt;You’ll see that &lt;a href=&quot;https://ellie-app.com/9m5z9YyLvTFa1&quot;&gt;after completing level
I&lt;/a&gt;, your warrior will be
automatically teleported to the next level, which looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5a924dcf922568d1dadcb25ef5c3d157/30c92/level-two.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB3ElEQVR42q2UUUvbUBiGc06IQlu2ixndjY3NKsVEhf2o3XgjU1C88Cd4t4tWhLa2szTS2pYg27V4UdhPWKltoYLQaFvbZCXwjpyYWnCCa3rgJW9I8vC933dyuGAwiEAgAOcaCoWm0iSD4zgOM5ZreF7AwqKMD6IMcUnCJ1lGJCJDkiTIzEde+Gh0lb0zNyc8AwkhzCyIEXw7/YOjEwsn329g2yYeHwdoNBoYjUbo9XpoNpuwbRuGYaDdbmNkDfBwb0BRVMaglDpAym7EpVWcloFjDdD0Abw1HA7H3jTNse92u3i4/Y2ucYeNjc1nIMe5Fb57/xFbu2V82S5jey8FXS+hWLxAKpVCpVJBoVBAOp2GruvI5XKoVqvo9/totVqIxWKTwOman0wmWaWdTgeKovwbSCgPQngQSsHzPBOd8I4EwR2AU6WznN6+CnyLnj5CPB6HZVmo1WrjyE8Dng6Yz+fHQ1NV1X+FmUyGAZ0tNJPIiUSC7c96ve5vyh5QO9fcvWmZUNdnETmddSPfGVDWfEQm1P0RDo8P8Mu+xmWjhJWYNPlsOuCBtoNr/ETJOoOkLvsH7me/4go/UDSyCCs+gJ4WwyKin2WsrIchzAsvz8OZH7D/HZ0QFtFrgae/Zv9ZEKz01JQAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm warrior level two&quot;
        title=&quot;&quot;
        src=&quot;/static/5a924dcf922568d1dadcb25ef5c3d157/f058b/level-two.png&quot;
        srcset=&quot;/static/5a924dcf922568d1dadcb25ef5c3d157/c26ae/level-two.png 158w,
/static/5a924dcf922568d1dadcb25ef5c3d157/6bdcf/level-two.png 315w,
/static/5a924dcf922568d1dadcb25ef5c3d157/f058b/level-two.png 630w,
/static/5a924dcf922568d1dadcb25ef5c3d157/30c92/level-two.png 874w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Our warrior can only move right each step, and since the dungeon turns
downwards, it gets stuck there. Poor fella.&lt;/p&gt;
&lt;p&gt;It’s time to look more in depth at a function inside the &lt;code class=&quot;language-text&quot;&gt;Map&lt;/code&gt; module:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-| Provides a list of everything the warrior can see in a
specific direction. The first item of the list will be the
one tile away. The second item will be two tiles away, etc.
-}&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;look&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Coordinate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Tile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What’s that &lt;code class=&quot;language-text&quot;&gt;Tile&lt;/code&gt; value?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Tile&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Wall&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;SpawnPoint&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Item&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The simplest way to pass this level is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;check if we can move right; if so, proceed&lt;/li&gt;
&lt;li&gt;check if we can move down; if so, proceed.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;

        _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;

                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;

                _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I know, I know, there is some duplication. Let’s resist the urge to
refactor straight away and enjoy our fleeting moment of success. 🍵&lt;/p&gt;
&lt;h2 id=&quot;level-iii&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-iii&quot; aria-label=&quot;level iii permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level III&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://ellie-app.com/9m5QgdLcLzva1&quot;&gt;Here&lt;/a&gt; we are.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4f3b0f2f93c661fd92030f6170e4d77e/b94e3/level-three.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAABYlAAAWJQFJUiTwAAACbklEQVR42rVUS09aURAG/oYmhD/QRX8A3XQHUS5IAEPCS5SnCZgm3UoTN110w4Y14eFFngK1PBITN9UFy24ErLZJTXHXcqFC8jUz1iq5bWpTOsnJnJk58/Hd7wxHoVAoMOf1nwCXzDEEnrXx8tUuDg+bEMUc6vU69vb22FerVRQKBdRqNc41Gg3kcjkcHR1hZ2fnPqCSN89fvEWyCrzr4cE2mUzYEzhhKJXKO4aPHuugfRqGYHJhczMIl8sNv98Pj8fDfmNjA2tra/D5fJxzOp2Ix+OYTqdIp9Pz0ZBAyUgGGUOt9glWV+0QBAE2mw1GoxFWqxUmk4m9xWLhvd1uh0aj4R5iTPZLhq1Wi4vj8XhGn/H420/NxqObmtls5p5AIMBxuVyWM8xkMpAkCScnJ+h0Ojg+PsbV4ArdXhcXn89x9qmP0+4phsMhdHrdDEPqlQHSSJCR6BQbDMscE1j1WsS+tIuLwTnnDIJhhmGpVJID0myRra+v38zl0hLHxKwqidj/IuLsss+5ZcMyn6HbJyMyMkASloxGgmK9Xg9pKPEnfxx8wPnle/T6PYxGI67RGa/Xyz3ZbFYOmM/nuUjzRvHKygrHpOutERgZ1e4zLBaLcsBUKsVFt9vNsVqt5kZiIwgG1pT2dMNU++OlVCoVLjocjgcPtsvl+v1gJ5NJnr1EIsG3FwwGsbW1hVAoxD4SiSAcDiMajXKO6nT2+nrCX8c49wGbzSb/Gv03/+pxmH7FwevaHXOVSsWbWCyGdrvNetBzRZ5koBskT8KLosgzRzk6Q5Px5qCO2PY2Y/zAmvMDu7CwAFqLi4v/tG5xvgO0ulp6dx60sgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm warrior level three&quot;
        title=&quot;&quot;
        src=&quot;/static/4f3b0f2f93c661fd92030f6170e4d77e/f058b/level-three.png&quot;
        srcset=&quot;/static/4f3b0f2f93c661fd92030f6170e4d77e/c26ae/level-three.png 158w,
/static/4f3b0f2f93c661fd92030f6170e4d77e/6bdcf/level-three.png 315w,
/static/4f3b0f2f93c661fd92030f6170e4d77e/f058b/level-three.png 630w,
/static/4f3b0f2f93c661fd92030f6170e4d77e/40601/level-three.png 945w,
/static/4f3b0f2f93c661fd92030f6170e4d77e/b94e3/level-three.png 1126w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Things are getting more complicated, and it’s clear that our nesting of
case expressions won’t fit the bill any longer. We need our warrior to try
to walk into any possible direction. We can do this by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;folding over a list of possible directions&lt;/li&gt;
&lt;li&gt;checking if we found a good direction to move&lt;/li&gt;
&lt;li&gt;if yes, we are done&lt;/li&gt;
&lt;li&gt;if no, try with the next direction.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To represent the idea that we might have found a good move we’re going to
use a &lt;code class=&quot;language-text&quot;&gt;Maybe Warrior.Action&lt;/code&gt; as the value of the accumulator.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;checkDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Up&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.foldl&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt;

                    &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;checkDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.withDefault&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately this is the result…&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/6c1dddca8c8f8f79ad6becffb3be17a4/level-three-oopsie.gif&quot; alt=&quot;Elm warrior level three oopsie&quot;&gt;&lt;/p&gt;
&lt;p&gt;The problem with our approach is that we’re using a stateless algorithm and
we’re not checking if we already visited the same tile in the past. Now
let’s take another look at the &lt;code class=&quot;language-text&quot;&gt;History&lt;/code&gt; module. We’ll find this function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-| Returns a list of the state of a warrior and the map,
going back to the first turn. The first element in the list
will represent the state of the warrior and the map at the
beginning of that warrior&apos;s last turn.
-}&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;previousStates&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What we get is a list of all previous states of our warrior, along with the
state of the map at the time. So we can use the &lt;code class=&quot;language-text&quot;&gt;position&lt;/code&gt; function from
the &lt;code class=&quot;language-text&quot;&gt;Warrior&lt;/code&gt; module to detect if we ever visited that tile before.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;alreadyVisited&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;History.previousStates&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.any&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;Warrior.position&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token hvariable&quot;&gt;checkDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;alreadyVisited&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
                        &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;

                    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                        &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Up&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.foldl&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                    &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt;

                    &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;checkDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token constant&quot;&gt;Nothing&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.withDefault&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tada! 🎉&lt;/p&gt;
&lt;h2 id=&quot;level-iv&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-iv&quot; aria-label=&quot;level iv permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level IV&lt;/h2&gt;
&lt;p&gt;We are &lt;a href=&quot;https://ellie-app.com/9mqpJDnTq8ca1&quot;&gt;here&lt;/a&gt; now.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/4e1d58c9f838d7872318d8122ccabbed/b94e3/level-four.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAABYlAAAWJQFJUiTwAAACVklEQVR42q1US4hSYRRWbykK6cI3vlNauRGcwYWL9kWtprJFJsysBDURWs8iqKVEm6aVkjslZ3BskULtatWuteJ7VNQEH2hf/EcddMzBoblwOP8959zvfuf188RiMTaJRCKZnyVzEUNySTwTHo/HwzXLqkEgEJB2OneQPc3g6EMc/sgx/JFPeH8Ux2nmGDu7uxTD3eDA3eQg4ASbATmOI7239wjsGU+At3Hg3Ufgd29Ktieep9sz5PP5pC2W2wgGAwiGIvjyrY7P+RJehF8iFAzAarNRzB2nDfuvn+HuY/dmwIsild4iVn+mAygU8hXfw9A9/MIPvPl6OLPxLwAydgtZpG4ymXF21kKpVIZtzkwoEpJ+8Pw+fuI7XsUPt2eo0WgwmUzQ7/dhMBhWfAf7B8T+JH2yXK6ZUyaTQaVSQS6XQ6lUQqFQkM1ut6PVaqFSqcDhcEAqldJPRCIR/H4/ASYSiXXAdDpNzlqtRrrRaGA8HqPZbJIeDAZot9sYDodkW47NZDKbAcvlMgEwzdKsVqsExs71eh29Xo9sLKZQKGA6nSKVSq0DMtrsCYfDlC5rgF6vh8vlQqfTITC32002i8UCq9UKs9lMcVqtdr0pyWSSAH0+30rh1Wo1RqMRut0ugW29erFYjAC9Xu9sNISz0WAgrHasKYzZYpuWR2yxDLNZnL/k83kCDAQCK4BsVGgFx2NKc3mbLmXo8XgQjUbhdDpXdlqn01H9isUiTCbT9oD/2hh2NhqNxJB180oM2bW1qM3yR2zIc7kcstnseTevzPBaL9j/lb9rF5Mj80e9oAAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm warrior level four&quot;
        title=&quot;&quot;
        src=&quot;/static/4e1d58c9f838d7872318d8122ccabbed/f058b/level-four.png&quot;
        srcset=&quot;/static/4e1d58c9f838d7872318d8122ccabbed/c26ae/level-four.png 158w,
/static/4e1d58c9f838d7872318d8122ccabbed/6bdcf/level-four.png 315w,
/static/4e1d58c9f838d7872318d8122ccabbed/f058b/level-four.png 630w,
/static/4e1d58c9f838d7872318d8122ccabbed/40601/level-four.png 945w,
/static/4e1d58c9f838d7872318d8122ccabbed/b94e3/level-four.png 1126w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Our warrior is now stuck on the top right corner. Why is that? Well, we
just added some logic that makes the warrior skip tiles which have been
visited in the past. In this case, we went down a path which turned out to
be a dead end, so we &lt;strong&gt;need to backtrack&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Instead of completely avoiding to step on a tile that has already been
visited, we can think which are the possibilities when we want to explore
the world in a certain direction. We can find:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the exit tile&lt;/li&gt;
&lt;li&gt;an empty unvisited tile&lt;/li&gt;
&lt;li&gt;an empty already visited tile&lt;/li&gt;
&lt;li&gt;a wall tile&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What we can do is to assign a value to each of these possibilities, so
that we can choose the best available move every time. One great thing
about Elm is how easy it is to create types for everything:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMoveUnvisited&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMoveVisited&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As a matter of fact, we are very interested in how many times we have
already visited a tile, because we can use that information to resolve ties
when deciding which cells to visit. Let’s change the type to reflect
this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt; that we attached to &lt;code class=&quot;language-text&quot;&gt;CanMove&lt;/code&gt; describes how many times we have
visited that tile in the past. So now all we have to do is to rewrite our
&lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt; function to consider each move and select the best. We can do
that using &lt;code class=&quot;language-text&quot;&gt;List.sortWith&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-| Sort values with a custom comparison function.

    sortWith flippedComparison [1,2,3,4,5] == [5,4,3,2,1]

    flippedComparison a b =
        case compare a b of
          LT -&gt; GT
          EQ -&gt; EQ
          GT -&gt; LT

This is also the most general sort function, allowing you
to define any other: `sort == sortWith compare`
-}&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;sortWith&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Order&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But we need to provide our own comparison function…&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Order&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;EQ&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;LT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token builtin&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;LT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;GT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;GT&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will notice that better options have a “lower value”: in this way when
we’re done sorting our list, the best option will be the head of the list.&lt;/p&gt;
&lt;p&gt;Now all we have to do is to change &lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt; to explore each direction and
choose the best option:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;History.previousStates&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.filter&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;Warrior.position&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;

        &lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;SpawnPoint&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

                _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Up&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.sortWith&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.head&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Tuple.second&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.withDefault&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point we can grab some popcorn and watch the progress…&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/8d01346559a1745f6db4a1ca86077235/progress-till-seven.gif&quot; alt=&quot;Elm warrior progress till seven&quot;&gt;&lt;/p&gt;
&lt;p&gt;Our warrior managed to complete in a swift dash levels four, five, six and
seven!&lt;/p&gt;
&lt;h2 id=&quot;level-viii&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-viii&quot; aria-label=&quot;level viii permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level VIII&lt;/h2&gt;
&lt;p&gt;We are stuck &lt;a href=&quot;https://ellie-app.com/9w6xzNZz7BNa1&quot;&gt;here&lt;/a&gt; now.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e5d7171e8413179856265fe4110f20cd/5eb90/level-eight.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 65.82278481012659%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB90lEQVR42o2Sy27TQBSGZ8EasUFCtHaghEq2qVggnF4ipVZjg/oU5QVYROJl4Al4iiwCiSIlQXLaLHJ1EssjKzfHjmyPZ8YDiWlCCwu+kUZnRufX0cz/g9VqhTEmhFBKt/u2iKJoe0MIwRhTSpP+xWIBwjBkjNm23W63J5PJYINlWb1ezzRN27b7/f5wODQMw7IsCOFgMJhOp4wx13V34larNZ/PCSEIIYwxQiiKomR4At6Q3DPGPM/7LY43sP8j6dyJGWOFQkGW32bPjo8zckImc1vJckbOnMgn2dOsoii6rjPGlsvlTqwo5wCAx0+ODl6IkiSIoiSKoiRJgiCIoigIAn/EPXr6EABQKpUYY47j7MS53Nke//rzV9rq+AT7U2/huV7kIz9YL2/l/WDfP335CAAol8v3xcp5DoAHh68uT7Pq+3fqRX6Npmqqpmmqllfz8uUbTtpbT/721+Srqw88t/8ynUqlOI7jeI7bv2V95Pln3PP0QVqSpHq9fufNcRxvMkCCMAzCNQihbVoSh8IwDILA931CyJ3fdjyn0+2YpvmnE6PRCEI4Ho9ns1li8r+t8hzv5vqmed10XTfpgBAWi8VarVatVnVdNwwDIXRfnGQbYxzHMaU0iiKEEKUUQlipVHRdbzQazWaz2+36vo8x3jb8yvZPHmNa/KWLJdsAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm warrior level eight&quot;
        title=&quot;&quot;
        src=&quot;/static/e5d7171e8413179856265fe4110f20cd/f058b/level-eight.png&quot;
        srcset=&quot;/static/e5d7171e8413179856265fe4110f20cd/c26ae/level-eight.png 158w,
/static/e5d7171e8413179856265fe4110f20cd/6bdcf/level-eight.png 315w,
/static/e5d7171e8413179856265fe4110f20cd/f058b/level-eight.png 630w,
/static/e5d7171e8413179856265fe4110f20cd/40601/level-eight.png 945w,
/static/e5d7171e8413179856265fe4110f20cd/78612/level-eight.png 1260w,
/static/e5d7171e8413179856265fe4110f20cd/5eb90/level-eight.png 1612w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We have met an enemy, exciting! Let’s add another option to &lt;code class=&quot;language-text&quot;&gt;Exploration&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enemy&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then follow some type errors to fix a missing branch in the case statement
within our &lt;code class=&quot;language-text&quot;&gt;compareExploration&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Order&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;EQ&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;second&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;LT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enemy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;LT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token builtin&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;y&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;LT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;GT&lt;/span&gt;

            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token constant&quot;&gt;GT&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, when we meet another warrior in our path we can attack them!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;SpawnPoint&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enemy&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Attack&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Success! 🎉&lt;/p&gt;
&lt;h2 id=&quot;level-ix&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-ix&quot; aria-label=&quot;level ix permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level IX&lt;/h2&gt;
&lt;p&gt;Let’s check &lt;a href=&quot;https://ellie-app.com/9w6Ps3mJNtJa1&quot;&gt;this&lt;/a&gt; out.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/fc05fb764009f9997bd04c62f419ed0f/b67f3/level-nine.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 72.78481012658227%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAABYlAAAWJQFJUiTwAAACEElEQVR42pXTTW7aQBQHcJ8hCwwkaptUwllUqrIpDalSKVKgtwp3gBPAusoBskTFiQQaHIH4cI3B2AgwkNbGZsyMeRUzFJoom/428+Txf56fZQur1QpjHDCY4UUQBL7vLxnf9zHGy3+EYTgcDgUAcByn3W6rqtpsNn8ymqYpimKaZq/XMwzDsqw+Y5qmYRgYYwCwbXsT9jyv1+sNh0Nd1/n2YDAwDCMIAgBYMyGzK/ZhAAjDkFK6u4OjlJIdVgZBQCldr9fbMD+mWCzGYrHj46PDw0gkIm5FxSgjRsW4GH93dCyKYj6f5/02YUopAORyOUEQTk4uz86+ZTLp6zSzXdKZdCaV+fzx+oMgCNls9mU4n9+Eb25qd3ckwIv576cn55f3tHBd1124Sxc3MPo+Kr4e5p0PDt7H46eSlEhICWmzbEkJ6a30Jn4aexnmM9/e3qZSqaurLxcXyVedfzq/vPiaTCYLhcI+DP9v/7YJJV29W61WXdflG4SQTqfTarUajUaL0TStXq+rqsoLXdf/dl6DPZ501A4PAwAhRFEUhFClUkEIybKMECqXy6VS6fHx8QcDANPpVNg9Bv96AGC1Wj08PNzf38uyXK1WEUL9ft+27dlsNp/Px+PxdDoFgMlk8srMhJBaraYw3W7XsizHcXY9ns3sed7iOdd1LcsyTXM0GvF/w7Ztfp1zHAdjbBjGH2XcwP1n7DvgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm warrior level nine&quot;
        title=&quot;&quot;
        src=&quot;/static/fc05fb764009f9997bd04c62f419ed0f/f058b/level-nine.png&quot;
        srcset=&quot;/static/fc05fb764009f9997bd04c62f419ed0f/c26ae/level-nine.png 158w,
/static/fc05fb764009f9997bd04c62f419ed0f/6bdcf/level-nine.png 315w,
/static/fc05fb764009f9997bd04c62f419ed0f/f058b/level-nine.png 630w,
/static/fc05fb764009f9997bd04c62f419ed0f/40601/level-nine.png 945w,
/static/fc05fb764009f9997bd04c62f419ed0f/78612/level-nine.png 1260w,
/static/fc05fb764009f9997bd04c62f419ed0f/b67f3/level-nine.png 1338w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now, this is a tricky one. We’re facing a guard that’s much stronger than
us. If we remain in the same spot and keep exchanging blows, we’ll die!&lt;/p&gt;
&lt;p&gt;As the level suggests, when we notice we’re not feeling well, we can try to
heal:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;{-| Get the health of a warrior.
-}&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;health&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;


&lt;span class=&quot;token comment&quot;&gt;{-| Get the maximum health the warrior can have.
    The warrior will start a map with this much health.
-}&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;maxHealth&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The issue is that if we try to heal while standing near the enemy, it will
keep attacking us, ultimately leading to our ghastly demise.&lt;/p&gt;
&lt;p&gt;Let’s do a bit of refactoring first: we’re going to split up our &lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt;
function into a couple of smaller functions:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;allDirections&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;allDirections&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Down&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Left&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Up&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;


&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Direction&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exploration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;History.previousStates&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.filter&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token hvariable&quot;&gt;Warrior.position&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Empty&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;SpawnPoint&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enemy&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Attack&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Exit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Freedom&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;


&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;allDirections&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.sortWith&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.head&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Tuple.second&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.withDefault&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can add a function to check if an enemy is nearby:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isEnemyNearby&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isEnemyNearby&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;allDirections&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.any&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;

                    _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                        &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And another one to tell if our warrior has been wounded:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isWounded&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isWounded&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Warrior.health&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Warrior.maxHealth&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In our &lt;code class=&quot;language-text&quot;&gt;exploreDirection&lt;/code&gt; function, when we meet another warrior we
can decide if we’re in a fighting mood:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isWounded&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enemy&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Attack&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;-- loads of other case branches&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And inside &lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;History&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Action&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;takeTurn&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;isEnemyNearby&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isWounded&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Warrior.Heal&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;allDirections&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.sortWith&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.head&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Tuple.second&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.withDefault&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What happens now?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/02d17b0e85534b0599c926009c32e363/pacifist.gif&quot; alt=&quot;Elm warrior pacifist&quot;&gt;&lt;/p&gt;
&lt;p&gt;Turns out that as soon as we move near the other warrior, we get attacked.
Therefore, we immediately run away to heal, then try again, then run away
again. I’m a pacifist at heart, but still I’d like to pass this level.&lt;/p&gt;
&lt;p&gt;What’s the solution this time? To endure a little bit of pain…&lt;/p&gt;
&lt;p&gt;Instead of running away as soon as we get slightly wounded, we can keep
fighting for a bit and only run away when we’re badly wounded.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isBadlyWounded&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isBadlyWounded&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Warrior.health&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Warrior.maxHealth&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, we’re going to replace &lt;code class=&quot;language-text&quot;&gt;isWounded&lt;/code&gt; inside &lt;code class=&quot;language-text&quot;&gt;exploreDirection&lt;/code&gt;.  We
still want the original function inside &lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt; because we want to heal
back to full health when we’re safe.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.look&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isBadlyWounded&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NoGo&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

            &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Enemy&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Attack&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;-- loads of other case branches&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Victory! 🎊&lt;/p&gt;
&lt;h2 id=&quot;level-x&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#level-x&quot; aria-label=&quot;level x permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Level X&lt;/h2&gt;
&lt;p&gt;We’re &lt;a href=&quot;https://ellie-app.com/9NGC6Q2YbZra1&quot;&gt;here&lt;/a&gt; now.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9d369b512f8afc28347ceea609f37769/9239a/level-ten.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.08860759493672%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAABYlAAAWJQFJUiTwAAACN0lEQVR42pWS0WvTUBTGL0mxVQc6mTIRHenwQVBY1m5TmIgPvspAIelA/Et8EPxbfBDqYPjky2BMBuuDNq2j68osTZq2Nm1ubs5NSZrlSJNtbvjk7/EePr5z7vcRxth4PGaMua4LAIwxAHAcBwA8z7Nt23Vd5xTXdTnnvu+HYUgpJaPRKIqiarW6v79fqVQ0TavVagcHB7VardFotFqtfr/f6XRarVa32zVNk1KKMZzziRgRDcPoxfT7fcuyKKWdTseyrCiK8B+Sx4nY8zxEPD4+TjZ3gQNAvB5wDvYplFKb2kN7aFmW7/uICACEc46ImqbNzNy8eiWTSQuiKIhiShDSgpBKpVKiKKZi0mJ66vJUJpPZ3NxERMYYAQBELJc1QsjsnUcrT9++eq0W1Jeq+kRV1xSlsL6+riiKoiov3jx/+OwBIaT4uYiIjuOciKvVn4SQtcL7j1+x99vl/BfAFwDdYTwMQuYw5jrf8duHT+8IIRsbGxfEP8plQSCXMtPTM/fn5qRs9q4k3ZCke5KUnZ/PSjGz87eu3742cS6eOic31+v11dXV5aX8Ul5eXJRlOSfL+YUFeSFGjsnJ+ZXlx7nc4tbW1snNyW//F3+jmpQEsd01D+uHw+HwbDYYDJrNZq/XMwzDNM3BYBAEQTI9l/No4mwa5t7enq7rSebJIdvb26VSaWdnR9f1drudxHvBOel2GIaIGIZhEAS+70dRdHR0tLu7W6lUSqWSYRiNRsPzvCDmrNt/ALgHTK9GsaYgAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Elm warrior level ten&quot;
        title=&quot;&quot;
        src=&quot;/static/9d369b512f8afc28347ceea609f37769/f058b/level-ten.png&quot;
        srcset=&quot;/static/9d369b512f8afc28347ceea609f37769/c26ae/level-ten.png 158w,
/static/9d369b512f8afc28347ceea609f37769/6bdcf/level-ten.png 315w,
/static/9d369b512f8afc28347ceea609f37769/f058b/level-ten.png 630w,
/static/9d369b512f8afc28347ceea609f37769/40601/level-ten.png 945w,
/static/9d369b512f8afc28347ceea609f37769/9239a/level-ten.png 1246w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ooh, items! Let’s go and grab them 🏴‍☠️&lt;/p&gt;
&lt;p&gt;We’ll need to add a new branch in the case statement in &lt;code class=&quot;language-text&quot;&gt;exploreDirection&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Item&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;CanMove&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;newCoords&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Move&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;dir&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And change our &lt;code class=&quot;language-text&quot;&gt;takeTurn&lt;/code&gt; function to pickup the item if we are standing on
it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isEnemyNearby&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;isWounded&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Map.lookDown&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Warrior.Heal&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Item&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
        &lt;span class=&quot;token constant&quot;&gt;Warrior.Pickup&lt;/span&gt;

    _ &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;allDirections&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;exploreDirection&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.sortWith&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;compareExploration&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.head&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Tuple.second&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Maybe.withDefault&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Warrior.Wait&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These changes will get us through &lt;a href=&quot;https://ellie-app.com/9NGZqhRjqTGa1&quot;&gt;both levels ten and
eleven&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;one-more-thing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#one-more-thing&quot; aria-label=&quot;one more thing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;One more thing…&lt;/h2&gt;
&lt;p&gt;On the last level we can notice something a bit weird:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/22aedf63fa0fdc5fdd457c1f2dfad7b7/indecision.gif&quot; alt=&quot;Elm warrior indecision&quot;&gt;&lt;/p&gt;
&lt;p&gt;After we run away from the fight and we heal ourselves to full health we
start doing a weird left and right dance on the first two tiles. Why is
that?&lt;/p&gt;
&lt;p&gt;It turns out we have a small bug in our &lt;code class=&quot;language-text&quot;&gt;visitedCount&lt;/code&gt; helper:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;History.previousStates&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.filter&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token hvariable&quot;&gt;Warrior.position&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since we spend many turns healing, we end up having a lot of states in our
history where the position of the warrior is the same, which ends up
inflating the number of times we have “visited” that tile. The fix is to
only consider the position of the warrior when it’s moving:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;visitedCount&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;History.previousStates&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;warrior&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;history&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.foldr&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.head&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Just&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;then&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt;

                &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;acc&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.filter&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; _ &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token hvariable&quot;&gt;Warrior.position&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;w&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;coords&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With our final fix &lt;a href=&quot;https://ellie-app.com/9NHbrJTp8QBa1&quot;&gt;in place&lt;/a&gt;, it’s showtime!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/d5f927411ca241f4e08415b84b5d357c/final.gif&quot; alt=&quot;Elm warrior final&quot;&gt;&lt;/p&gt;
&lt;p&gt;Thanks for reading! 👋&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Writing a program that writes itself]]></title><description><![CDATA[Recursion is one of those concepts in programming which have always been
incredibly fascinating to me. What do you mean that I can call the…]]></description><link>https://juliu.is/quine-quine/</link><guid isPermaLink="false">https://juliu.is/quine-quine/</guid><pubDate>Mon, 04 Nov 2019 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recursion is one of those concepts in programming which have always been
incredibly fascinating to me. &lt;em&gt;What do you mean that I can call the
function from the function itself?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, there is a class of programs that bring the whole idea of recursion
to a completely different level, which is programs that are able to
replicate themselves. These programs, named &lt;strong&gt;Quines&lt;/strong&gt;, produce a copy of
their own source code as their only output.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b4f6479f98439cc87c34f8e02a9f5461/b17f8/escher.jpg&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 84.81012658227847%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAARABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAEDBAL/xAAVAQEBAAAAAAAAAAAAAAAAAAAAAf/aAAwDAQACEAMQAAABs2qYoSOwZgf/xAAbEAADAAIDAAAAAAAAAAAAAAABAhEDMQASQf/aAAgBAQABBQJr2CLPccmWEk08bR3/AP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EAB4QAAEBCQAAAAAAAAAAAAAAAAABEBESICExYXGh/9oACAEBAAY/ArlesyPi0kv/xAAdEAEAAwABBQAAAAAAAAAAAAABABEhMRBBUWFx/9oACAEBAAE/IVngAc7wlrfVGxHhlqUKZfqCxvWFxCs4h1r/2gAMAwEAAgADAAAAECQ3/wD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAdEAACAwACAwAAAAAAAAAAAAAAAREhMUFxUWHB/9oACAEBAAE/EK26wV2zEKgDS7EXv2Dq1r6yBHJKd+35KIwluwok5dmZof/Z&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Drawing Hands, M.C.Escher&quot;
        title=&quot;&quot;
        src=&quot;/static/b4f6479f98439cc87c34f8e02a9f5461/828fb/escher.jpg&quot;
        srcset=&quot;/static/b4f6479f98439cc87c34f8e02a9f5461/ff44c/escher.jpg 158w,
/static/b4f6479f98439cc87c34f8e02a9f5461/a6688/escher.jpg 315w,
/static/b4f6479f98439cc87c34f8e02a9f5461/828fb/escher.jpg 630w,
/static/b4f6479f98439cc87c34f8e02a9f5461/0ede0/escher.jpg 945w,
/static/b4f6479f98439cc87c34f8e02a9f5461/3ac88/escher.jpg 1260w,
/static/b4f6479f98439cc87c34f8e02a9f5461/b17f8/escher.jpg 1600w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The name “quine” was introduced by Douglas Hofstadter in &lt;em&gt;Gödel, Escher,
Bach: An Eternal Golden Braid&lt;/em&gt; in honor of &lt;a href=&quot;https://en.wikipedia.org/wiki/Willard_Van_Orman_Quine&quot;&gt;Willard Van Orman
Quine&lt;/a&gt;, an American
analytic philosopher who made extensive studies in the field of
self-reference. There is a paradox named after him that goes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Yields falsehood when preceded by its quotation” yields falsehood when preceded by its quotation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a more elaborate version of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Liar_paradox&quot;&gt;Liar
paradox&lt;/a&gt;, where the sentence
&lt;code class=&quot;language-text&quot;&gt;Yields falsehood when preceded by its quotation&lt;/code&gt;, when preceded by itself
in quotation marks, gives a new expression. If this new expression is true,
then it says of itself that it must be false. But if it’s false, then what
it says of itself must be true.&lt;/p&gt;
&lt;p&gt;Pretty puzzling, huh?&lt;/p&gt;
&lt;h2 id=&quot;some-rules&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#some-rules&quot; aria-label=&quot;some rules permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some rules&lt;/h2&gt;
&lt;p&gt;Before we start and try to write a Quine, we have to define some ground
rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The program must produce its own source code when executed&lt;/li&gt;
&lt;li&gt;It must not use I/O to read its own source code&lt;/li&gt;
&lt;li&gt;It must not be an empty program&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;a-first-attempt&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-first-attempt&quot; aria-label=&quot;a first attempt permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A first attempt&lt;/h2&gt;
&lt;p&gt;If we had this simple Ruby program:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we executed it, we would get:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby quine.rb
hello&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So we could make our program to look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;puts \&quot;hello\&quot;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But running that would only yield:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby quine.rb
puts &lt;span class=&quot;token string&quot;&gt;&quot;hello&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As we can see, this approach won’t get us closer to the solution since
we’re always going to miss the outer &lt;code class=&quot;language-text&quot;&gt;puts&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;a-bit-of-self-reflection&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-bit-of-self-reflection&quot; aria-label=&quot;a bit of self reflection permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A bit of self reflection&lt;/h2&gt;
&lt;p&gt;Luckily in Ruby there is a simple way to escape this using
&lt;code class=&quot;language-text&quot;&gt;Object#inspect&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;puts src&quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src = &quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; src&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inspect&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby quine.rb
src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;puts src&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But we’re still missing the last line. What if we added the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; again
to the end of our &lt;code class=&quot;language-text&quot;&gt;puts&lt;/code&gt; statement, but this time as a normal string?&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;puts src&quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src = &quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; src&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inspect &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; src&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby quine.rb
src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;puts src&quot;&lt;/span&gt;puts src&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uh! Since the contents of the &lt;code class=&quot;language-text&quot;&gt;src&lt;/code&gt; string don’t really matter to the
behaviour of our program, we can get quite creative with it!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\nputs \&quot;src = \&quot; + src.inspect + src&quot;&lt;/span&gt;&lt;/span&gt;
puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;src = &quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; src&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inspect &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; src&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ruby quine.rb
src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token entity&quot; title=&quot;\n&quot;&gt;\n&lt;/span&gt;puts &lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt;src = &lt;span class=&quot;token entity&quot; title=&quot;\&amp;quot;&quot;&gt;\&quot;&lt;/span&gt; + src.inspect + src&quot;&lt;/span&gt;
puts &lt;span class=&quot;token string&quot;&gt;&quot;src = &quot;&lt;/span&gt; + src.inspect + src&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Tada! 🎉&lt;/p&gt;
&lt;h2 id=&quot;how-to-write-your-own-quine&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-to-write-your-own-quine&quot; aria-label=&quot;how to write your own quine permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How to write your own Quine&lt;/h2&gt;
&lt;p&gt;This simple example showed us some of the core ideas for writing a Quine:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We build the program in two parts, one that we call the &lt;em&gt;code&lt;/em&gt; and one
that we call the &lt;em&gt;data&lt;/em&gt;. The data part of the program is derived from the
code part, usually by some means of escaping.&lt;/li&gt;
&lt;li&gt;When executed, the code first uses the data to print the data.&lt;/li&gt;
&lt;li&gt;Then the code uses the data to print the code. This is generally easy
because we intentionally derived the data from the code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A great analogy of a Quine comes from cellular biology: if we think of the
cell as the &lt;strong&gt;code&lt;/strong&gt; and the cell’s DNA as the &lt;strong&gt;data&lt;/strong&gt;, then we’ll see that
the cell is able to replicate itself using the DNA, and this process
involves replicating the DNA itself. On the other hand the DNA contains
all the information for replicating the cell, but without the cell itself
it would just be an inert piece of data.&lt;/p&gt;
&lt;h2 id=&quot;quine-quine&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#quine-quine&quot; aria-label=&quot;quine quine permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Quine Quine&lt;/h2&gt;
&lt;p&gt;Douglas Hofstadter also invented the verb &lt;em&gt;to quine&lt;/em&gt;, which means “to write
something a first time, and then to write it a second time with quotation
marks around it”. For example, if we quine “say”, we would get “say ‘say’“.
If we were to quine “quine”, we would get “quine ‘quine’”, which itself is
a quine…&lt;/p&gt;
&lt;h2 id=&quot;testing-testing-testing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#testing-testing-testing&quot; aria-label=&quot;testing testing testing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Testing, testing, testing&lt;/h2&gt;
&lt;p&gt;When you’re trying to write your own Quine, you’ll get to a point when you
think you’ve reached a solution, but end up having to compare two printouts
which are not exactly human friendly. So you can use this bit of Bash
instead:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; quine.rb &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ruby quine.rb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IS QUINE&quot;&lt;/span&gt;
IS QUINE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you had make a mistake, it would print the diff like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; wrong.rb &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ruby wrong.rb&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IS QUINE&quot;&lt;/span&gt;
2c2
&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; puts &lt;span class=&quot;token string&quot;&gt;&quot;src = &quot;&lt;/span&gt; + src.inspect + src
---
&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; puts src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &quot; + src.inspect + src&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The weird looking &lt;code class=&quot;language-text&quot;&gt;&amp;lt;()&lt;/code&gt; is a Bash feature called &lt;a href=&quot;http://tldp.org/LDP/abs/html/process-sub.html&quot;&gt;process
substitution&lt;/a&gt; that allows
you to pass one command’s output to another program as if it were a file
name.&lt;/p&gt;
&lt;h2 id=&quot;a-quine-in-haskell&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-quine-in-haskell&quot; aria-label=&quot;a quine in haskell permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A Quine in Haskell&lt;/h2&gt;
&lt;p&gt;Here is a very elegant solution in Haskell:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;haskell&quot;&gt;&lt;pre class=&quot;language-haskell&quot;&gt;&lt;code class=&quot;language-haskell&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;putStr&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;src&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;main = putStr src &gt;&gt; print src\n  where src = &quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This works thanks to the &lt;code class=&quot;language-text&quot;&gt;where&lt;/code&gt; notation, where you can use a variable in
an expression before defining it. We first print the code using the normal
&lt;code class=&quot;language-text&quot;&gt;putStr&lt;/code&gt; function, then we print the data using &lt;code class=&quot;language-text&quot;&gt;print&lt;/code&gt;, which maintains
the double quotes around the string. The beauty of this solution is that
the data is barely escaped!&lt;/p&gt;
&lt;p&gt;Here it is in action:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ghc quine.hs
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; of &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Compiling Main             &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; quine.hs, quine.o &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Linking quine &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;.

$ &lt;span class=&quot;token function&quot;&gt;diff&lt;/span&gt; quine.hs &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;./quine&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IS QUINE&quot;&lt;/span&gt;
IS QUINE&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;a-quine-in-elm&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-quine-in-elm&quot; aria-label=&quot;a quine in elm permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A Quine in Elm?&lt;/h2&gt;
&lt;p&gt;We can almost directly port our Ruby code to Elm. The only challenge is
that browsers don’t usually recognize newlines literally, so that makes
escaping code quite daunting. But fear not, thanks to the amazing powers of
CSS and the
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/white-space&quot;&gt;white-space&lt;/a&gt;
property, we can make the browser behave:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;css&quot;&gt;&lt;pre class=&quot;language-css&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pre&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; monospace&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The other challenge is to be able to inspect the data in a literal way:
this can be achieved in Elm using the &lt;code class=&quot;language-text&quot;&gt;Debug#toString&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;So I challenge you to write your own implementation of a Quine in Elm. If
you get stuck at any point, you can check this &lt;a href=&quot;https://ellie-app.com/76YftNWMdDTa1&quot;&gt;working example on
Ellie&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Happy Quining!&lt;/p&gt;
&lt;h3 id=&quot;references&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#references&quot; aria-label=&quot;references permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.madore.org/~david/computers/quine.html&quot;&gt;David Madore’s Quines
page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://florian.github.io/quines&quot;&gt;Florian Harmann’s Quines blog post&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Performant Elm, Part III, Html.Lazy]]></title><description><![CDATA[Greetings traveler! This is the third instalment of a series on how to make
your Elm applications more performant. If you are into this kind…]]></description><link>https://juliu.is/performant-elm-html-lazy/</link><guid isPermaLink="false">https://juliu.is/performant-elm-html-lazy/</guid><pubDate>Mon, 21 Oct 2019 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Greetings traveler! This is the third instalment of a series on how to make
your Elm applications more performant. If you are into this kind of stuff,
you can read about &lt;a href=&quot;../performant-elm&quot;&gt;how to tell what your browser is really
doing&lt;/a&gt; and &lt;a href=&quot;../performant-elm-html-keyed&quot;&gt;how Html.Keyed can help you help Elm to be
faster&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Today we are talk about being lazy. As an Italian, I know a thing or two
about being lazy. I’m not talking “Oh I spent Sunday binge-watching Derry
Girls” lazy, but more something like &lt;a href=&quot;https://www.theguardian.com/world/2018/apr/06/former-postman-found-with-400kg-of-undelivered-mail-in-italy&quot;&gt;“I got caught with 400kg of undelivered
mail in my flat”&lt;/a&gt; sort of lazy.&lt;/p&gt;
&lt;p&gt;So &lt;a href=&quot;https://guide.elm-lang.org/optimization/lazy.html&quot;&gt;the Elm Guide&lt;/a&gt; does a fantastic job at explaining what &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt; does. I really recommend going there and reading about it. Anyway, the main idea of it is this function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;lazy&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;msg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, we pass two arguments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;function that takes a thing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;thing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you’re learning about functional programming, it’s common to bump into
something called &lt;a href=&quot;https://en.wikipedia.org/wiki/Referential_transparency&quot;&gt;referential
transparency&lt;/a&gt;
(don’t open that link, that’s five minutes of your life you’re never
getting back). In Elm it’s simply called:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Same input, same output&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You’re always guaranteed that any function in Elm will return the same
output, &lt;strong&gt;if&lt;/strong&gt; you pass the same input. So in the context of web
applications, by using &lt;code class=&quot;language-text&quot;&gt;lazy&lt;/code&gt; you are telling Elm that you know for sure
that if the data ain’t changing, then the view shouldn’t change either.&lt;/p&gt;
&lt;h2 id=&quot;intermezzo-sieve-of-eratosthenes&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#intermezzo-sieve-of-eratosthenes&quot; aria-label=&quot;intermezzo sieve of eratosthenes permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Intermezzo, Sieve of Eratosthenes&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes&quot;&gt;Sieve of
Eratosthenes&lt;/a&gt; is a
very ancient algorithm devised for finding all prime numbers up to a given
limit. It works by marking each multiple of a prime number as non-prime, so
that when we’re done we’re left with all the prime numbers. Its beauty can
be admired in the following GIF:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/6420e3488e509dce176a1e957ea07ff5/sieve.gif&quot; alt=&quot;Sieve of Erasthothenes&quot;&gt;&lt;/p&gt;
&lt;p&gt;A naive implementation of the algorithm in Elm would look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;sieve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;sieve&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;List.range&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt;

        &lt;span class=&quot;token hvariable&quot;&gt;last&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;toFloat&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sqrt&lt;/span&gt;
                &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;round&lt;/span&gt;

        &lt;span class=&quot;token hvariable&quot;&gt;isMultiple&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;modBy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;List.range&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;last&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.foldl&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt;
                &lt;span class=&quot;token hvariable&quot;&gt;List.filter&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;isMultiple&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token hvariable&quot;&gt;result&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;numbers&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can use this function to make our Elm code as slow as we want 🎉&lt;/p&gt;
&lt;h2 id=&quot;our-testbed-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#our-testbed-example&quot; aria-label=&quot;our testbed example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Our testbed example&lt;/h2&gt;
&lt;p&gt;I have built a small Ellie app that calculates the number of prime numbers
up to a certain limit, which you can find
&lt;a href=&quot;https://ellie-app.com/bc2LYDftdQKa1&quot;&gt;here&lt;/a&gt;. Here’s a GIF of the app in
action:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/c978d72430e5dae4ee36f6528556c358/before.gif&quot; alt=&quot;Prime before&quot;&gt;&lt;/p&gt;
&lt;p&gt;We are going to focus on the &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt; function, which looks like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;onClick&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Toggle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Toggle color&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;-- style stuff&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;There are &quot;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;sieve&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; prime numbers between between 2 and &quot;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can notice there is a noticeable lag in the UI after pressing the
“Toggle Color” button: this happens because after receiving the &lt;code class=&quot;language-text&quot;&gt;Toggle&lt;/code&gt;
event, the Elm runtime needs to rerun the &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt; function, which triggers
again the sieve computation.&lt;/p&gt;
&lt;h2 id=&quot;htmllazy-to-the-rescue&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#htmllazy-to-the-rescue&quot; aria-label=&quot;htmllazy to the rescue permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Html.Lazy to the rescue&lt;/h2&gt;
&lt;p&gt;We can change this line from:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;to this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.Lazy.lazy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and we get &lt;a href=&quot;https://ellie-app.com/bc2KLQMsYkYa1&quot;&gt;this result&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/9fa2b8893de5f0241e9e79508df53747/after.gif&quot; alt=&quot;Prime after&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can now see that after the initial call, we never really get inside the
&lt;code class=&quot;language-text&quot;&gt;viewPrime&lt;/code&gt; function anymore, thus making our application blazing fast. 🤟&lt;/p&gt;
&lt;h2 id=&quot;happily-ever-after&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#happily-ever-after&quot; aria-label=&quot;happily ever after permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Happily ever after?&lt;/h2&gt;
&lt;p&gt;Unfortunately, as almost everything in else in life, nothing is as simple
as it seems. If you have ever tried to use &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt; and failed to see
any improvements, you know how frustrating it can be. So I’m going to list
some common reasons on why it might not be working.&lt;/p&gt;
&lt;h3 id=&quot;using-anonymous-functions&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-anonymous-functions&quot; aria-label=&quot;using anonymous functions permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using anonymous functions&lt;/h3&gt;
&lt;p&gt;A very simple way to break &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt; is to replace this line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.Lazy.lazy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;with this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.Lazy.lazy&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;\&lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can check it out &lt;a href=&quot;https://ellie-app.com/bc2MVVJTLJwa1&quot;&gt;here&lt;/a&gt;. Why is
that? Because &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt; needs to associate the cached value with a
precise function, but specifying an anonymous function forces the runtime
to recreate that function every time the &lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt; is invoked.&lt;/p&gt;
&lt;h3 id=&quot;constructing-records-on-the-fly&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#constructing-records-on-the-fly&quot; aria-label=&quot;constructing records on the fly permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Constructing records on the fly&lt;/h3&gt;
&lt;p&gt;A similar problem happens when we construct a record on the fly and pass it
to &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt;. Imagine our &lt;code class=&quot;language-text&quot;&gt;viewPrime&lt;/code&gt; looked like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;There are &quot;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;sieve&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; prime numbers between between 2 and &quot;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we called it by writing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Html.Lazy.lazy&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;200000&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You will see the app going back to &lt;a href=&quot;https://ellie-app.com/bc2Q8mxQF8Ma1&quot;&gt;being slow
again&lt;/a&gt;. This happens because when we
build a new record we invalidate the caching mechanism of &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;reference-equality&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reference-equality&quot; aria-label=&quot;reference equality permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reference equality&lt;/h3&gt;
&lt;p&gt;The Elm Guide has this very interesting section:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When are two values “the same” though? To optimize for performance, we use JavaScript’s &lt;code class=&quot;language-text&quot;&gt;===&lt;/code&gt; operator behind the scenes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Structural equality is used for &lt;code class=&quot;language-text&quot;&gt;Int&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Float&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;Char&lt;/code&gt;, and &lt;code class=&quot;language-text&quot;&gt;Bool&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Reference equality is used for records, lists, custom types, dictionaries, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Structural equality means that &lt;code class=&quot;language-text&quot;&gt;4&lt;/code&gt; is the same as &lt;code class=&quot;language-text&quot;&gt;4&lt;/code&gt; no matter how you produced those values. Reference equality means the actual pointer in memory has to be the same. Using reference equality is always cheap &lt;code class=&quot;language-text&quot;&gt;O (1)&lt;/code&gt;, even when the data structure has thousands or millions of entries. So this is mostly about making sure that using &lt;code class=&quot;language-text&quot;&gt;lazy&lt;/code&gt; will never slow your code down a bunch by accident. All the checks are super cheap!&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Let’s try to reproduce this error case by changing the &lt;code class=&quot;language-text&quot;&gt;viewPrime&lt;/code&gt; function
to take a list of integers:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;viewPrime&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limits&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;token hvariable&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
            &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;text&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;There are &quot;&lt;/span&gt;
                        &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;sieve&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&gt;&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;List.length&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot; prime numbers between between 2 and &quot;&lt;/span&gt;
                        &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limit&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limits&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you click on the toggle &lt;a href=&quot;https://ellie-app.com/bc2Rn9t8HKxa1&quot;&gt;now&lt;/a&gt;,
you’ll see that we’re back to being slow.&lt;/p&gt;
&lt;p&gt;So what can we do when we need to use a record, a list, a dictionary or a
custom type as a &lt;strong&gt;thing&lt;/strong&gt; to pass to &lt;code class=&quot;language-text&quot;&gt;lazy&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;The easiest solution is to store it inside our &lt;code class=&quot;language-text&quot;&gt;Model&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Color&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;limits&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now the reference won’t change as long as we don’t change our model. Check
out the updated version &lt;a href=&quot;https://ellie-app.com/bc2RXrWn6fKa1&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-end&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-end&quot; aria-label=&quot;the end permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The End&lt;/h2&gt;
&lt;p&gt;Remember to always benchmark your application before and after &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt;,
so you can prove to your team lead that you have actually made the
application faster 🤡&lt;/p&gt;
&lt;p&gt;This article concludes the series on writing performant Elm, thanks for
reading!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Performant Elm, Part II, Html.Keyed]]></title><description><![CDATA[This is the second post in a series which explores optimization techniques
to build performant Elm applications. But first, let’s take a bit…]]></description><link>https://juliu.is/performant-elm-html-keyed/</link><guid isPermaLink="false">https://juliu.is/performant-elm-html-keyed/</guid><pubDate>Mon, 07 Oct 2019 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This is the second post in a series which explores optimization techniques
to build performant Elm applications. But first, let’s take a bit of a
detour and talk about &lt;a href=&quot;https://en.wikipedia.org/wiki/Thomas_the_Apostle&quot;&gt;Saint Thomas&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Saint Thomas was one of twelve apostles of Jesus and he is also known as
&lt;em&gt;Doubting Thomas&lt;/em&gt;. Why is that? Because of one specific episode in the New
Testament. In the Gospel of John it is said that when he heard that Jesus
had risen from the dead and appeared to the other apostles, he said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Except I shall see on his hands the print of the nails, and put my finger
into the print of the nails, and thrust my hand into his side, I will not
believe.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But when Jesus appeared later and invited Thomas to touch his wounds and
behold him, Thomas believed and exclaimed “My Lord and my God”. At which point Jesus said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thomas, because thou hast seen me, thou hast believed: blessed are
they that have not seen, and yet have believed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, my point about optimization techniques in general is: be more like
Saint Thomas, aka Doubting Thomas. Don’t believe what the documentation
says, but instead go and see for yourself. Then, &lt;em&gt;believe&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So first of all I would recommend reading &lt;a href=&quot;../performant-elm&quot;&gt;the first post in this
series&lt;/a&gt;, which shows you how to use your browser
profiling tools to perform repeatable measurements.&lt;/p&gt;
&lt;h2 id=&quot;what-is-htmlkeyed&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-is-htmlkeyed&quot; aria-label=&quot;what is htmlkeyed permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What is Html.Keyed&lt;/h2&gt;
&lt;p&gt;The wonderful &lt;a href=&quot;https://guide.elm-lang.org/optimization/keyed.html&quot;&gt;Elm
Guide&lt;/a&gt; tells us that
&lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; is particularly helpful for lists of data in your interface
that must support &lt;strong&gt;insertion&lt;/strong&gt;, &lt;strong&gt;removal&lt;/strong&gt;, and &lt;strong&gt;reordering&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Imagine you have a list of words in ascending order: now you change to sort
order to be descending. The virtual DOM algorithm will then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compare the previous first word with the current first word&lt;/li&gt;
&lt;li&gt;Compare the previous second word with the current second word&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can tell, the algorithm will have to compare each and every one of
our words! Instead, it could have done a much faster job and rearranged the
nodes in the DOM to appease our new sort order.&lt;/p&gt;
&lt;p&gt;So the basic idea of &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; is that you associate a &lt;code class=&quot;language-text&quot;&gt;String&lt;/code&gt; to your
&lt;code class=&quot;language-text&quot;&gt;Html msg&lt;/code&gt; so that the virtual DOM diffing algorithm knows in advance which
nodes have to be compared.&lt;/p&gt;
&lt;h2 id=&quot;a-working-example&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#a-working-example&quot; aria-label=&quot;a working example permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;A working example&lt;/h2&gt;
&lt;p&gt;Let’s unleash our inner Doubting Thomas and test out these assumptions. In
most UNIX systems there is a dictionary of words in
&lt;code class=&quot;language-text&quot;&gt;/usr/share/dict/words&lt;/code&gt;, so I’ve taken some of those and wrote a &lt;a
href=&quot;https://ellie-app.com/6VDSqp2zqrYa1&quot; target=&quot;_blank&quot;&gt;small Ellie
app&lt;/a&gt; to display them. It looks something like this:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9a27bc649df9fcebf11d01fbee8c00bd/0330c/ellie-example.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.68354430379746%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAADb0lEQVR42mWU609bZRzH+Rt4NQPaEkPpufW0p+f0wmUM516goS2zK+AMBpYto2yOctHIvRTaAoYxcIiAcQMbGZCMedkSE5epiTfcYkw0S4zxkvjGxDf+Ax/znOJg8STf/HJO8nyf7+V5TkkwGERXPWiKikdSUSQVl1vC5XJRVVVFlduN0+kkHo+Tm8kzN/8G2VyG/EyW+YU5pnITZPMZRsdGGBocokT36QQ1k+fqTvBsw3HqAzUErDCa148iNtI0ysrKyOWm+frur3y8ucenuz9we/M+HxX2uLN5nw82vuWvP/9BPCW614uheqn2h7BCAVRFRZZkJEnC7XajKArl5eWMj02Qe2WH07XTdJ64zMvPzNnoOD5HW7XY7GGRUFhSZRXLtDAt07YpiAQEaZGwjIl0hsLiF6STBfK92+R7t+w53bdNuqvATw/+KBKKRR5Vw9ANTL+JLMuPyA4rTI9nWJn6hIHTawyfWWeo8zpDZ9YZ7LjOxZPLfP/VL0VCtyShqRq6x4fX60NVVcQ3aR+HFS6O3KYr8iaplhV6EiukEiv0tq5yIfbWAWFRoQefx8IwAph+P7Ks/M+yULi1/CWzr+5wZfgWlwdvMvf6TeaHdsmltvjxwe/7Ct0Suq4RsHQMnxdFUe0cH7P8ZLGUq2N36GtbZbDjGn1ta7bSvtZVkpGrfPf5zwcKNVXF69MxrRCGVYuqenBLRYUiApFhZmKSjfnPGDm7zuTFTRtTl26Q7bnB+PnCgUKxSFisrKxEkhU8uh9JVu13cbiFyiNPHGFsNM27s3cZPbdhk010v2+XM3J2g4HT7zyeoWEYBINhwjVHqa2txbJMTNPEsizCobBtO5edtku50LxE/4trtlW7lJZVuqNLB4RCRX39MeKn4kSjEZqamohGo0QiEXsmEgkikSZy2TzvLdxjpn/nUSFiilLyh0vx+/24XFW4NQVJlnja6eQphwOnw4HD4aCiooLS0lIG+l9jYfhDktFFUi1v03NqmZ7EMqnWFbqaFvnm3v5NaWhowDD81B2rp+ZoHTXVYWpCIaxAgEAgYFsWsVyZX2BraY/J5DazvbeYSf2HXTJd2/z28O8iofjbNDY28lJ7O4l4nJPNMZpjMduuQCwWs2NIJrvpbOsh8fw5WiPnbbRFu+hoSdH+wiXSY9NcK6zzL8R/h+GhflgNAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Ellie example&quot;
        title=&quot;&quot;
        src=&quot;/static/9a27bc649df9fcebf11d01fbee8c00bd/f058b/ellie-example.png&quot;
        srcset=&quot;/static/9a27bc649df9fcebf11d01fbee8c00bd/c26ae/ellie-example.png 158w,
/static/9a27bc649df9fcebf11d01fbee8c00bd/6bdcf/ellie-example.png 315w,
/static/9a27bc649df9fcebf11d01fbee8c00bd/f058b/ellie-example.png 630w,
/static/9a27bc649df9fcebf11d01fbee8c00bd/40601/ellie-example.png 945w,
/static/9a27bc649df9fcebf11d01fbee8c00bd/78612/ellie-example.png 1260w,
/static/9a27bc649df9fcebf11d01fbee8c00bd/0330c/ellie-example.png 2458w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;To simulate a slighly more complex HTML structure, I’ve broken each word
into characters and repeated them twenty times. Also, if you click the
dropdown at the top of the page, it will toggle between ascending and
descending sorting.&lt;/p&gt;
&lt;p&gt;If we record a performance readout of this example, this is what we’ll see:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b8bc24d5c26726170812ccf1c0f50913/9d6a9/before.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 67.72151898734178%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB0klEQVR42pWLyYrbQBRF9f9k3QTyAUkWWQZ6lUBjsN3BCNvyIMuyplJpqJJrLo2tCk53REI2zuVy4A3Hyn4lz3OEUIUxSFM/iFKYpSksS4RxVRQlIZT/FXatyhJTKwiCKIoghEVRCKm5aLlolBJas6aVUpKyhAhnSnHBxW+XCyEo41Z8SxJHURgBgQIaPNbp02UdHlfUs8nuGXk2cebl+ZS6l73rH13/ePD2XuDuXMeK8wsWWUFAyTIiAar2VAQgB2mJghjEMIcYRzDPSZngMCMgrZIEhSXLcYUsmLgU+1okkka1gI2CnfIH7fXa7dWx18ehdofa7bV7Wyp30OdenQadGGOs3eLr5tu70/wh+PFQOB9i+4s9v6yXl80i3j6DzSLZLsF2OTG25+fVzPccoNvayqLVevYe7D6hw+fq+LEKvxNhKB8JGyk3r5xK2Ej4eGUjFWPTjxbncGc/AnuGQ6eKHeIfatnVg9HdWPdvnDqNujVNbyxO4zR4oqEnQMqSiCeJUoNqjWzGiVOnUTavMss4z1Q7SD0q/XI7d0Y198lCIFG3qjOyHd/4x98dsm7//b5LlorKptedUe3/yW1vrOpKrpRfKa8IZ0JL3d7VumNc/gTUXQ03cNfuBgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Performance before&quot;
        title=&quot;&quot;
        src=&quot;/static/b8bc24d5c26726170812ccf1c0f50913/f058b/before.png&quot;
        srcset=&quot;/static/b8bc24d5c26726170812ccf1c0f50913/c26ae/before.png 158w,
/static/b8bc24d5c26726170812ccf1c0f50913/6bdcf/before.png 315w,
/static/b8bc24d5c26726170812ccf1c0f50913/f058b/before.png 630w,
/static/b8bc24d5c26726170812ccf1c0f50913/40601/before.png 945w,
/static/b8bc24d5c26726170812ccf1c0f50913/78612/before.png 1260w,
/static/b8bc24d5c26726170812ccf1c0f50913/9d6a9/before.png 2256w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Let’s break down the graph (you can click on the image to see more details):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;From the moment we click the button, we spend around 1000ms in scripting&lt;/li&gt;
&lt;li&gt;Then follows 250ms of style recalculation&lt;/li&gt;
&lt;li&gt;Then follows 2000ms of layout rendering&lt;/li&gt;
&lt;li&gt;Which is followed by 500ms of layer tree updating&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I would like to focus on is the &lt;strong&gt;right hand side&lt;/strong&gt; of the scripting
portion: you can see that there are a lot of small function calls happening
at the end. If you zoom in, you will see that the root function
&lt;code class=&quot;language-text&quot;&gt;_VirtualDom_applyPatches&lt;/code&gt; has instantiated many thousands of times
&lt;code class=&quot;language-text&quot;&gt;_VirtualDom_applyPatchesHelp&lt;/code&gt;. You can also see this in the “Bottom-Up” view:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/e34da86237d40329052ca9bc2b11dcf8/bb051/zoomed.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 36.708860759493675%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABYlAAAWJQFJUiTwAAABOklEQVR42nWQy2rcQBBF9f+/lVWyCIQkM4M8o45a6pb6pWdLPTbSnBCBDU6cggtVm8OpmxlrUVozjhPj0CPFmUqc6WxJMJJKlRhr8D4QQsA6d+zLsnyY7AFUqiWEjthX9EFTXb/Q3j7RqW/EZ4tqa86XJ66F4HTJKUTJNM18NFmaHUrmdM2J6H4yjBFZ3o57aE5MyeGCpZQ1tW54uhXopqXrB/Z9PyCPx+MtWYodVn4lyM/M5jvLEmmtJwTHaHPmwdE0Ddfi11HLtu+kdGdd0wH4B7jtoFWFb3ImL44eqlrhfKC3gnHQKK245FeMdawpvXvxFfr28h9t6wPzPLL0kvs90RrLHCPzYIhDgbUaYz3ruvL88vLO6m9otm0bZVUfRlOnWNd4lO5DoO8ck9cIIfhxuiBr9V+zV+BvT8UVBh00el8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Zoomed in&quot;
        title=&quot;&quot;
        src=&quot;/static/e34da86237d40329052ca9bc2b11dcf8/f058b/zoomed.png&quot;
        srcset=&quot;/static/e34da86237d40329052ca9bc2b11dcf8/c26ae/zoomed.png 158w,
/static/e34da86237d40329052ca9bc2b11dcf8/6bdcf/zoomed.png 315w,
/static/e34da86237d40329052ca9bc2b11dcf8/f058b/zoomed.png 630w,
/static/e34da86237d40329052ca9bc2b11dcf8/40601/zoomed.png 945w,
/static/e34da86237d40329052ca9bc2b11dcf8/bb051/zoomed.png 1212w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;introducing-htmlkeyed&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introducing-htmlkeyed&quot; aria-label=&quot;introducing htmlkeyed permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introducing Html.Keyed&lt;/h2&gt;
&lt;p&gt;Now let’s replace the current rendering logic with &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt;. We’ll
replace this line of code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;Html.ul&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attr.class&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;entries&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewEntry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortedEntries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;with this line of code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;Html.Keyed.ul&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;Attr.class&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;entries&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;List.map&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewKeyedEntry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;sortedEntries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and implement this new view helper:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;viewKeyedEntry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Html&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Msg&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;viewKeyedEntry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;String.fromInt&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;viewEntry&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can play around with the &lt;a href=&quot;https://ellie-app.com/6VDSnNwFcKTa1&quot;
target=&quot;_blank&quot;&gt;new Ellie app&lt;/a&gt;. Now let’s make another performance
measurement!&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/600ae9e0ef1583d5f21f784126742c59/c679a/after.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 62.0253164556962%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAABYlAAAWJQFJUiTwAAABr0lEQVR42pWPS4+bMBSF+f+7/oL+gM6m6qq7Vl20UiZU6iQkJEB4G/AD4wcGG/CISaYTdTOqdXR0fHS/K12nLMuiKACo6qYmGEOEc4AaiDCBjNGOtaRFtCNSMCm5eH2cdZgwJ8vSKIziOG5q1HWcIshhiEtQZ7TJSZ2R5AziUwES3OS4rkEJyqsKUDpZkeVlXlQ5qBHhXV5GXf0jCc77P8T30OGpOe7gcQ9PHvH31SU/nZKTHx+D9BzFgVM1JaaAKwZJzHiqDVQjMiabpniaYm2iYQjNFN+kU60ToxNjysUuTlqgNAGE9b77Pfj1Mds9VN6X/cY7bAJ/e/Hd6PD4Eh4vx23ku5HvXrzN+eh6Ha0cyAyThg2261C4+fT09UPhPkA8IjrjdsF0RnTCdMF0Qe18C2tphNJOK+deW6Hmwdo62O9+fg6333o+9sb249Jr+1fy5XtzbZWxTitmOVoxLFJbAjN4/t0WoRytHOzqd1pn3twq/QavrVBKmqU36/p/yHdgOSy8V/cT78O0n9V6yXqhUOP/wZiKjivKFWU9Fb0YJjFMXJlruNe1fPVJjtMzjXCgrTIUgZEAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Performance after&quot;
        title=&quot;&quot;
        src=&quot;/static/600ae9e0ef1583d5f21f784126742c59/f058b/after.png&quot;
        srcset=&quot;/static/600ae9e0ef1583d5f21f784126742c59/c26ae/after.png 158w,
/static/600ae9e0ef1583d5f21f784126742c59/6bdcf/after.png 315w,
/static/600ae9e0ef1583d5f21f784126742c59/f058b/after.png 630w,
/static/600ae9e0ef1583d5f21f784126742c59/40601/after.png 945w,
/static/600ae9e0ef1583d5f21f784126742c59/78612/after.png 1260w,
/static/600ae9e0ef1583d5f21f784126742c59/c679a/after.png 2460w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the general shape of the performance graph hasn’t changed.
The browser is still spending most of the time recalculating styles,
updating the layout and the layer tree. Unfortunately &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; is not
black magic and cannot make your application faster if the bottleneck is
somewhere else.&lt;/p&gt;
&lt;p&gt;But if we zoom in the scripting section we’ll see an interesting change.
First of all, it’s clear that our browser has been less busy: the usage
pattern is way less fragmented. When we look at the call stack,
&lt;code class=&quot;language-text&quot;&gt;_VirtualDom_applyPatches&lt;/code&gt; now calls &lt;code class=&quot;language-text&quot;&gt;_VirtualDom_applyPatchesHelp&lt;/code&gt; only
&lt;strong&gt;once&lt;/strong&gt;! This is even more evident in the “Bottom-Up” view:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/58313e11a9ed4b96c9815f01b2f6d809/7321b/zoomed-after.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.177215189873415%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABYlAAAWJQFJUiTwAAABVUlEQVR42l2R6W7iQBCEef/3ykpoV5tEWkRwjPF9MPacHjDB8EUeKQhtSaX+013d1bU6pBlZXmCtRWvFIYnYx1sGUaOGlkPySZYlaG1QSuG9ZxxHnHNh5n+u7vc7ZVXT9wPGGGwfU0QvdIc1st4w6Zgme+MjXhbnoc9ax+12C1zmn7ma55lBSqyzeH/CmoE6WSPLP9jmHeM1ndFUVU17FKRZTt20SKW4Xq8sWIR+sJrnG1XTMUgVNkslSba/6NI1qnxFjIZcanYfEWlesNnuiOI9TdtxPp8fgo8Lr18netFidI93GucMTfoXVb/iun+YUdMqTVlWtN2RoxAI0T/EnhEEvamosg19E2GHPART7n8jsjW6fkebnqJp2O4+yYqSfpDhjyqEpAOf7a8W+4tdN3q8H5mmM6Ir0bLGyxTlDUfnuUwTl8sXo/fhOn86hZ//1CWLRfAbBlkSXOT8JIwAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Zoomed in after&quot;
        title=&quot;&quot;
        src=&quot;/static/58313e11a9ed4b96c9815f01b2f6d809/f058b/zoomed-after.png&quot;
        srcset=&quot;/static/58313e11a9ed4b96c9815f01b2f6d809/c26ae/zoomed-after.png 158w,
/static/58313e11a9ed4b96c9815f01b2f6d809/6bdcf/zoomed-after.png 315w,
/static/58313e11a9ed4b96c9815f01b2f6d809/f058b/zoomed-after.png 630w,
/static/58313e11a9ed4b96c9815f01b2f6d809/40601/zoomed-after.png 945w,
/static/58313e11a9ed4b96c9815f01b2f6d809/7321b/zoomed-after.png 1184w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We’ve made the code twice as fast 🤟&lt;/p&gt;
&lt;h2 id=&quot;one-more-thing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#one-more-thing&quot; aria-label=&quot;one more thing permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;One More Thing&lt;/h2&gt;
&lt;p&gt;So far we have seen the benefits of &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; as far as it concerns
performance. But another great use case of this library is &lt;strong&gt;UI consistency&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Let’s go back to the original version without &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; and add a little
checkbox near each word. Now if I checked a word and then changed the
sorting order, I would expect the checked box to follow the word.&lt;/p&gt;
&lt;p&gt;Right? Wrong! &lt;a href=&quot;https://ellie-app.com/6VDZZNkyfXca1&quot; target=&quot;_blank&quot;&gt;See for yourself&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/587ff6771a54095dfc6b0b40a9a3e451/oopsie.gif&quot; alt=&quot;Oopsie&quot;&gt;&lt;/p&gt;
&lt;p&gt;This happens because the virtual DOM diffing doesn’t really understand that
the checkboxes &lt;em&gt;belong&lt;/em&gt; to each word, and therefore decides that the best
action to take is just to leave them there. Note that this happens because
we are using the DOM to store the state of our checkboxes, so Elm has no
knowledge that we care about those values.&lt;/p&gt;
&lt;p&gt;If we apply the &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; change again by replacing &lt;code class=&quot;language-text&quot;&gt;viewEntry&lt;/code&gt; with
&lt;code class=&quot;language-text&quot;&gt;viewKeyedEntry&lt;/code&gt;, we communicate our intention that these elements belong
to the same unit and therefore need to be considered as a whole. Check out
the &lt;a href=&quot;https://ellie-app.com/6RvNwJfQdMna1&quot; target=&quot;_blank&quot;&gt;updated
version&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/8700d6a03940f78130c9946c5d140587/fixed.gif&quot; alt=&quot;Fixed&quot;&gt;&lt;/p&gt;
&lt;p&gt;Amazing 🎉&lt;/p&gt;
&lt;p&gt;In the next post of this series, we will move on to deconstruct the
mysteries of &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt;. Thanks for reading!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Performant Elm, Part I]]></title><description><![CDATA[You have written your first application in Elm. Congratulations my friend,
the hard work has finally paid off. Now it’s time to relax and…]]></description><link>https://juliu.is/performant-elm/</link><guid isPermaLink="false">https://juliu.is/performant-elm/</guid><pubDate>Mon, 08 Jul 2019 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;You have written your first application in Elm. Congratulations my friend,
the hard work has finally paid off. Now it’s time to relax and enjoy the
pure bliss that is maintaining and refactoring Elm code.&lt;/p&gt;
&lt;p&gt;But wait a second, someone tells you the app feels a bit sluggish to use.
Mh. I thought that writing pure functions would automatically make code
fast. Okay. Let’s try to stay calm.&lt;/p&gt;
&lt;p&gt;The app looks fast at a first glance. To be fair, you’re probably using a
quad-core machine with 16 GB of RAM. Maybe you should see how the app
behaves on a lower end device. In Chrome, you bring up the inspector, then
go to Performance tab and choose how much you want to throttle your CPU.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5be75c57145cde1ea07b99ef2396d515/89587/chrome-throttling.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.0506329113924%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC2klEQVR42qWS224jRRCG+2qfAO7hbdjL9Rp4Ay6x4JWQuEUiixAojkDLbtaCOOt47KwdO5Px+BR7Zrrn0HPqqfpROwcQYiUkSv1Nt1rVNVV/lfjj1+5HzuDN1yvX/9Jfbzrrzbbjr7adi/G0M5rOO6PJf+X6q97Z4GNx/vbtp2EYIFExgiiCimPESQqpEiiVQsbJI1GcPiKTuz2UClIpxLHE0HE+F5evf38WXy9RrvZ1qslEGRul2VTcGEJjiMlwDcMGBmQMUBlwbWAag7oxZMjoCnUQVzg9PX0ufvruqDU9u0B0s6YsI440OMyIfR2xm+15F6dcx8xlTExlwjAhc6WYYs2INaeq5P7Yo+Fkhe4vr9uie3LSmrs3CKQiAHxYYARhicU2g9QV/m78j52o4aW/IH+xwMvfXrXFzz/+0Ho3GsJfeAQGW0cyjJMvQlx9kyMpQ6SJxn4fQGt9F4z5gLXGGJ7PpjQeOeh2u21x9OJFy3EcbLY74vsMiRjOtzFuXmVIiwSmqlDkGqauH/N7CGiM4cm7S5rNXZydX7TF0dH3rZEzRBhG9FCJ/YRNjWVWYpsQMgOkNVA2QFwASfmXBE3T8OV4RJ63wHhy1RbHx8etq+kEm/WKtNacZRksi/UOs02EyW0Md5vCDTTCvMDFymC0rMBNhdJmXpS89D3yPRf9N7226PV6Ld/34fs+bTYbDoIAUkrc7vYHwmCPJFWI17fYD+fYO9dIgrt5VUpZOE1TkmGIc9uU8XjcsmJrrSnPc87z3OpiSwERoWkIhggmKVCsIpRrCZOXhzG0flZDYwxVVYXpbNYW0+n02b0cxjb4AWtlUVCWZZSlKRVVeaCy8259+NG3sW/tz+fz+XMxm83a+Beznd7to0P596UdzlEY4X3muu5not/vfyKl3CilbqSUnkUp5YWR9Fbb8HBW6u7+fdi3URStB4PBUyGEeCKE+EAI8eH/xMZ48icBRwJlbu1VZgAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Chrome CPU Throttling&quot;
        title=&quot;&quot;
        src=&quot;/static/5be75c57145cde1ea07b99ef2396d515/f058b/chrome-throttling.png&quot;
        srcset=&quot;/static/5be75c57145cde1ea07b99ef2396d515/c26ae/chrome-throttling.png 158w,
/static/5be75c57145cde1ea07b99ef2396d515/6bdcf/chrome-throttling.png 315w,
/static/5be75c57145cde1ea07b99ef2396d515/f058b/chrome-throttling.png 630w,
/static/5be75c57145cde1ea07b99ef2396d515/40601/chrome-throttling.png 945w,
/static/5be75c57145cde1ea07b99ef2396d515/78612/chrome-throttling.png 1260w,
/static/5be75c57145cde1ea07b99ef2396d515/89587/chrome-throttling.png 2624w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;When you click around the app now, you can clearly see it’s quite sluggish.
Mh. Time to unleash the power of the flamegraph. You can start recording a
session, then click around the app as a normal user would. Easy peasy. When
all is done, you should see something like this.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/572b7372323ab05efa9abcfbd2aa4635/89587/chrome-performance.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.0506329113924%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAADPElEQVR42oWQ244bRRCG5yr3IHIPbwOXcUx4Cyx4F96BKyQQEiLktGHJBu+ud9e79trj4xw9PTM9fZiDx93u/pENUgiKREmf9FfVXyVVORevX3x6d/P222jpf+2HUS/N8l6UpL27ybw3ma97Y3fZG00X/8OyN3KX3/QHw8+cwWDwJc1zSCGRFQUYF6AFR5ykIBlFwQUKLt+DifIfJChjKBgH4ww3w9uvnNH9/SO9U9hlhVKbXLdNrbMs1YwVuiylPgSAf2G1UkprpXS70zrh0FULZY3GcDh87Liu24G14OXOlLWyjbK2Vta2+lCFxQd4F7B6D2sMzH6/h+u6Xef+ftyxxuL5iJi3i9zO0wqkUiCVRrnVULsWjDEIIY6UZXlECgHO+aFvYa1RSmE8mXSds7M3nTCMEUWxiTeJzSkDZRzhJkUYEyQkRZpmyHIKQlLkeQ52/FkJxiWEKG1VVoZRisHJSde5vLzqxN4SUeQbkhJLkwAyDyBTH5KlEDRBJTlEkSKJPCQkgZDs6BE0QMESmwtqMpri8vy861xd33YomaOqM1NtpRX5FHxzBhL0wQsfnM4hRXLUrFihrCW4JGDxH0iCPqJkbEPqGT9Z4dnJs65zcnrWCTYEXJaG8cpSWSIgMXJZYqv2qJXGVmk0B71T0HqPqmmwoTl406LV1tZVa9pWYXL44W8np53w9hd4nmuiTWTnN09x1/8eZPgDUn8EsuyDEg9FOEHqD5HwAvPFNaan34GMf0SRrmxRbg0vK7jzddd5fe52DidV28Y0ytgkGmI9ewqeXUEIAsF8yJJBHrTYoNoBWR5jdvcTWHoNWea23sHIZoeJu+w6r/qzR0wUKOtGV1ttks3ELKYvDc1GRkhquNgYWQkjZHbkMExZbubTl6bIxkbIYl/toGV9WLh47Px+seyWtUCj92j3QJbOsJ6/gGBT1I1EVWWotw3qhqOqOVoDcFFgNXsOXhw85XGu3hnMFt4T5+dXbz6fDO833q+X69Vs7bmzkedOLjzfm3pBGHhBsPaCMPSC0D8SxcTzfM+buQPPW//tCWOyDsI4/rN//oXjOM4Dx3E+cRzn4Ts+evh+/iE+/m/tsOPBXz2M9JJrVBHeAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Chrome Performance&quot;
        title=&quot;&quot;
        src=&quot;/static/572b7372323ab05efa9abcfbd2aa4635/f058b/chrome-performance.png&quot;
        srcset=&quot;/static/572b7372323ab05efa9abcfbd2aa4635/c26ae/chrome-performance.png 158w,
/static/572b7372323ab05efa9abcfbd2aa4635/6bdcf/chrome-performance.png 315w,
/static/572b7372323ab05efa9abcfbd2aa4635/f058b/chrome-performance.png 630w,
/static/572b7372323ab05efa9abcfbd2aa4635/40601/chrome-performance.png 945w,
/static/572b7372323ab05efa9abcfbd2aa4635/78612/chrome-performance.png 1260w,
/static/572b7372323ab05efa9abcfbd2aa4635/89587/chrome-performance.png 2624w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That looks quite exotic, but let’s not lose hope. The &lt;span
style=&quot;background-color: #f3d07c;&quot;&gt;yellow parts&lt;/span&gt; of the graph
represent the time your browser spent executing scripts, while the &lt;span
style=&quot;background-color: #ae99eb;&quot;&gt;purple parts&lt;/span&gt; denote the time it
took to render. You can also see small red corners scattered through the
graph: those represent when the user has experienced noticeable delays
while using the application. You can find out more information about what
it means
&lt;a href=&quot;https://developers.google.com/web/fundamentals/performance/rail#goals-and-guidelines&quot; title=&quot;Measure Performance with the RAIL Model&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You’ll also notice you can select a smaller time interval and start digging
into more specific bits of what your application is doing at a certain
time. For example, if you highlight the first big chunk of scripting and
then look in the lower panel, you will find a tab named “Bottom-Up”.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/70fe78c0c82b89594bc5c36dc75ea2b0/89587/bottom-up.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.0506329113924%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC40lEQVR42qXT3Y7jNBQHcF/tE8A9vA1cbrfAW1DBM/EC3LEjdmG6sO1sZ1pmmzZJ20mTtGkTJ42d700c+4+SQUi7IC0Sln46x/bRkS3Z5Hb88jPtfvq9Z7nfukdvRMNo5Pl0pBm7kbGzR+uNNVqZDx/R1Vjf3dzdf07m8/lXlyhCmqQI4xiMJ7jEDCefIggviHmCmKfvYUn2iKd9bcw4GGdYaqtvyErXn4q6QUUvTX2ORFWWIgyp4IyJLMtE27YCwHtE0wghGlE3rQgSiPwdGqgW+nr9jJimOZCtRFk1sigbVdatKmqhyloo0Uol21YJIVTbtj0p5d95p266uZJCCOimOSQ3NzeDs+/jTENJo1hdWIIoZnBPATw/RBRFYIyBc97HLM1Q5AWK4lFZ5KosS5kwhsV43DWcDmx7D8uypOs6yj+fkPAYLI5AKe1dLo+54zg9GlKEf6EhVWEUyiAIcPfmzZC8+GU82JkaXNeS7vGgPHuJ7PQ76H4KZ7+BszfgOlaf23sT7uEA27Fgb2bYmXNsd5ra2htp7gw8//lqSKaT6SDwz93VJGexypIYVc5QlymaKkdTZX2s+/xRlaeoco4y46iKVNVVLouMY7G4G5Iffrwe3JkBXq8DOVm6arIOcK1FeLHk+OkPhuf3/3TVR97X/KZzdb3icqxFuPp1OiST2XzgHD2caCRdz1NHP4S+P8OhBcJcIUgl6Ae6tTCT2NMG11qmJmYpJ3qKl69mQ7IxjUGSpCjSSF48TaUXG3nG8F9G3UhY50odw1oeghJvNWNIDEN/2v2OhAUisGeSh3vpnc+yrN5JAN2zk1J9QCoJKMlzIad62i4eCrHYpbhdrJ+R7XY7TLMcVZkhubjIuN8/h0a0Hz+hABwqcIpbHKMay5X5NVks5l+4h+P5eNjbD8bMcS3NMUzdoTR0Es4dxti/6vZ8GjtvN4Gztqi93gWn19PbLwkh5Akh5BNCyKf/U9fjyZ+6+fT72Cd+agAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Bottom-up&quot;
        title=&quot;&quot;
        src=&quot;/static/70fe78c0c82b89594bc5c36dc75ea2b0/f058b/bottom-up.png&quot;
        srcset=&quot;/static/70fe78c0c82b89594bc5c36dc75ea2b0/c26ae/bottom-up.png 158w,
/static/70fe78c0c82b89594bc5c36dc75ea2b0/6bdcf/bottom-up.png 315w,
/static/70fe78c0c82b89594bc5c36dc75ea2b0/f058b/bottom-up.png 630w,
/static/70fe78c0c82b89594bc5c36dc75ea2b0/40601/bottom-up.png 945w,
/static/70fe78c0c82b89594bc5c36dc75ea2b0/78612/bottom-up.png 1260w,
/static/70fe78c0c82b89594bc5c36dc75ea2b0/89587/bottom-up.png 2624w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The first entry says &lt;code class=&quot;language-text&quot;&gt;_Utils_eqHelp&lt;/code&gt;, and apparently that function took the
most time to execute. This is curious, because we don’t expect our
application to spend so much time comparing things. By clicking on the
right hand side, we will be able to see which module is the cause of this
performance problem.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/495faa113d798949de834b18dd741a2a/89587/source.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.0506329113924%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAC2ElEQVR42qWT247rNBSGc7WfAO7hbeBydw/wFlTwgFygYdgj0Y4qOp1O27RNm4PrOE7sHOvTj5wyoC2BuOCXPnklsf8sLy8Hv/380xfLxccfk/3p+1OcTGnOpgmh0+V6N13vjtPVZj99fg3/Az9n/8PjbPFlMJ/PvykYgxQSOecoK4GCl0gJxSUvwCsBXslPKEV9o5LjXF5WKKsSvy+fvwueX17e66tCTwt1zZjuu07nOdVVWeq6rrUxRgP4BK2U1lrpqzL6IqCbAQrOYLV6+RBsNpuJNRZdp2zbXl2vrOuVcd3VOGOss9aP2hljnNbGWWvH+A2lnTMWVmuN9Xp9Fzw8/DrJsgyUFZaVlYuSC04JQZwRkEuOoijBGEdZVhBCoGkatG074uOy5E5KYYuiwOPj413wy8PHyevuiDRNrRDCEUIgRQFlLGSjsF5znM81hLjC+FTs3zjnwDl3F0r9WiyXy7tg8TSbrDZ7LFcvNo4Tl1MKZw28hlYjSwQuVEAphX9S3bSuKLiVUt62PJvNJuF+j3B/sP5vlDFYAJK1IGkDQjrkrAOlHapqQNMo9K1C32to7ZBz6XbhwWaE3Azn8/mk4BxFUVheVu4YEvQ5RcM6JMcKSSrH7QqhIGs1Gg6tQteqsQR5ztzrZmsJudy2/PT0NPHpNnVj67Z1dBtBrQ9QYkB6rnE6S1TiirpW4/hG12lopTD0gxuGwfpD2m63N0Nf0LqufR0cZTkcMOIPhZIWBevAy9631ngQ8Pg5zsG3DgDr4zAMR8P33lBKqaWUNqfUGt+AzvlSWjNom0SVJbSxXn8uHvEy3tE5fwGw2+0+BIvF4s73U9d1Y29xzv/K4E3+seFXsLwf6/ZvOhwO3wb39/dfxXGcxXF8jOM42u/DKAx3kRchJMoyEl3oJUrPaRSG5+h0isf3t29ZxBiLqqo6cs7TxWLxdRAEwbsgCD4LguDz/4n3ePcH3U8FAGiPxxUAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Source&quot;
        title=&quot;&quot;
        src=&quot;/static/495faa113d798949de834b18dd741a2a/f058b/source.png&quot;
        srcset=&quot;/static/495faa113d798949de834b18dd741a2a/c26ae/source.png 158w,
/static/495faa113d798949de834b18dd741a2a/6bdcf/source.png 315w,
/static/495faa113d798949de834b18dd741a2a/f058b/source.png 630w,
/static/495faa113d798949de834b18dd741a2a/40601/source.png 945w,
/static/495faa113d798949de834b18dd741a2a/78612/source.png 1260w,
/static/495faa113d798949de834b18dd741a2a/89587/source.png 2624w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the function causing slowdown seems to be the aptly named
&lt;code class=&quot;language-text&quot;&gt;author$project$Page$Learn$SelfReviews$Revise$Highlighter$isSpace&lt;/code&gt;. Let’s
look at what that function does:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;isSpace&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;token hvariable&quot;&gt;isSpace&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;List.member&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos; &apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\t&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\n&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{000D}&apos;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;-- what follows is a list of unicode characters used&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;-- as spaces: http://jkorpela.fi/chars/spaces.html&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{00A0}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{1680}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{180E}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2000}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2001}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2002}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2003}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2004}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2005}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2006}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2007}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2008}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{2009}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{200A}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{200B}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{202F}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{205F}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{3000}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&apos;\u{FEFF}&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Uh! That is really surprising. Usually iterating over a list is really
fast, but in this case it seems that we are spending almost 90% of our
time inside this function. As you probably know, the algorithmic complexity
of iterating over a list is &lt;em&gt;O(n)&lt;/em&gt;: we could easily improve that by
building a set that contains all the desired characters and checking
if the current character is part of that set. The Elm standard library
implements a set using a dict, which is in turn implemented using a
red-black tree, which means that the time complexity will become
&lt;em&gt;O(log(n))&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So we can change the code that looked like this&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token hvariable&quot;&gt;sameToken&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;isSpace&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;isSpace&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;into something that looks like this&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;elm&quot;&gt;&lt;pre class=&quot;language-elm&quot;&gt;&lt;code class=&quot;language-elm&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;-- This is a very hot path in the code. So we build a set once&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;-- and use it to determine if a character is a space or not.&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;spaceSet&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token hvariable&quot;&gt;Set.fromList&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;spaceCharacters&lt;/span&gt;

&lt;span class=&quot;token hvariable&quot;&gt;sameToken&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt; _&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char2&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;Set.member&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char1&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;spaceSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class=&quot;token builtin&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token hvariable&quot;&gt;Set.member&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;char2&lt;/span&gt; &lt;span class=&quot;token hvariable&quot;&gt;spaceSet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this little change in place, we can repeat the performance
measurement&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/6f1a4ebc0b1182eab6a91492c56ecb7a/89587/append-child.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 74.0506329113924%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAADIUlEQVR42qXM3W7jRBQH8LnaJ4B7eBu43GyAtyCCt+EJYAVIe8HSgsouKt1usmmbfqRNHMexx3Fie8aeGceJ8zGe+aOkEmIv0F5wpJ/Opw65OH31Sf+m/e1sEn4dRrMW41lrlrBWfzhuDcdB62E0ad073gfsbybfdC5vPiW9Xu+LPMuwKBbgQkCqArmQmCcMKc8hVAGhFu+RRflILQ63QipIJXHXv/+KPAwGT/V2hzXLd9s40+uq0pwzraTUZVnquq41gPfo3U5rvdPbXa3TAnq5wQ62xuDh4RlxHKdhaoNqvTOramerbW1XG22rrba6NtbUtdVa27quD4wx/9R7W73vrdFaY+A4TdLpdBpxkiBOuUl4bjNRIBMS0zjFLGHIsgxSKiilIKXEYlFitVr9y9JWVWUKKdE7PW2SdrvdCIIAlAaGscRyniDPc3DGwDkH549P95mGFGFIwVgKnnGwx53lWWYYY7jodJrk7dvzBg0DeOO+4eGZZUEbs8hHFAwQUQd0fIPQu8V06mE6o/D9IfzRFXzvBuPAgUdd69GRcSdDHP9+1CR/nZ01PH+MYOabMJ7aOE+Rygy8kEjyBMVmhXK3RrFZI18uD1lt1ijW5WGnNitbbFamXFe4u71rkp+ff9dwbn9B4BybYHhkqfsagXuOcHSMaPQrJvcvMOz9ADr4EZGz9xNmznPQ4R+Yuq8QjU9s5L02bH4Px6VN8vLPk0af9eBkl8bJu9YVN5guPIzEFRzZRXd6guPb7/EmeIFueoRL/hvesZcYiWu44hrD/MKOxLVhRQzPjZrk9Oy8MUsZaMyNF07tvk54Bq4UmJRIpcA844gYQ5znSKQ4YFIgUxJiIa1cKJMLgYtut0nenLefRlMfceTryXhsounYBCE1LE2NFMIoKU2h1COpDv3jTJokzU3fTeuBx/TDOEH73eUzMhi6TSUzrIsQMp9jWcyQpDGWqwofitoCWWkhV4Aoawwc90vS7nQ/8yZeHFEnmPg+pZMR7d/d0nmc0KIoqJTyPxVK0mWp6LIsgoUS86urq88JIeQJIeQjQsjH/9P+x5O/AWL462Q45Pm4AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Append Child&quot;
        title=&quot;&quot;
        src=&quot;/static/6f1a4ebc0b1182eab6a91492c56ecb7a/f058b/append-child.png&quot;
        srcset=&quot;/static/6f1a4ebc0b1182eab6a91492c56ecb7a/c26ae/append-child.png 158w,
/static/6f1a4ebc0b1182eab6a91492c56ecb7a/6bdcf/append-child.png 315w,
/static/6f1a4ebc0b1182eab6a91492c56ecb7a/f058b/append-child.png 630w,
/static/6f1a4ebc0b1182eab6a91492c56ecb7a/40601/append-child.png 945w,
/static/6f1a4ebc0b1182eab6a91492c56ecb7a/78612/append-child.png 1260w,
/static/6f1a4ebc0b1182eab6a91492c56ecb7a/89587/append-child.png 2624w&quot;
        sizes=&quot;(max-width: 630px) 100vw, 630px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
        decoding=&quot;async&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Now our browser is spending most of its time adding elements to the DOM
instead of just comparing things. We can also notice that there is no huge
outlier anymore: the current top function, &lt;code class=&quot;language-text&quot;&gt;appendChild&lt;/code&gt;, uses 15% of the
total time while previously &lt;code class=&quot;language-text&quot;&gt;_Utils_eqHelp&lt;/code&gt; was taking almost 90% of the
total time. When we try clicking around the application, we notice an
extreme performance speedup when using the application. Albeit this is
still not optimal, it’s a &lt;strong&gt;huge&lt;/strong&gt; improvement with a very small code
change. Look at how the shape of the performance graph has changed:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/b31edea8823f7fd01f421d9fef89f13a/before-after.gif&quot; alt=&quot;Before After&quot;&gt;&lt;/p&gt;
&lt;p&gt;I hope that after reading this you will be less intimidated to dive in
performance measurements and get the most out of your browser inspector. In
future blog posts we will explore what else we can do to make our Elm
applications faster, in particular using &lt;code class=&quot;language-text&quot;&gt;Html.Keyed&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;Html.Lazy&lt;/code&gt;.&lt;/p&gt;</content:encoded></item></channel></rss>