<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://hakon.gylterud.net/articles.atom</id>
  <title>Håkon Robbestad Gylterud — Articles</title>
  <updated>2024-05-25T12:00:00Z</updated>
  <link rel="self" type="application/atom+xml" href="https://hakon.gylterud.net/articles.atom"/>
  <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/"/>
  <author><name>Håkon Robbestad Gylterud</name></author>
  <entry>
    <id>https://hakon.gylterud.net/programming/applicative-logic.html</id>
    <title>Applicative logic</title>
    <updated>2024-05-25T12:00:00Z</updated>
    <published>2024-05-25T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/programming/applicative-logic.html"/>
    <content type="html">&lt;p&gt;Note: You can find the functions below in the module
Control.Applicative.Logic (&lt;a
href="https://github.com/typeterrorist/applicative-logic"&gt;GitHub&lt;/a&gt;, &lt;a
href="https://hackage.haskell.org/package/applicative-logic"&gt;Hackage&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The following is an exploration of a few functions I found while
writing various Haskell programs over the years. Their names collide
with some standard function in Prelude, which is unfortunate, and while
the new functions cannot be used as drop-in replacements of the prelude
functions, they are morally generalisations. Also, note that the order I
present my insights here are almost the exact opposite of the order in
which I “discovered” them. I say “discovered” because I am presumably
not the first one to discover these as they are very general. In fact,
some of them are already in the standard library (albeit under a
different name).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;tl;dr: Many functions involving booleans can be generalised to
involve &lt;code&gt;(Alternative f, Monoid a) =&amp;gt; f a&lt;/code&gt;
instead.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="a-boolean-is-maybe-true"&gt;A boolean is maybe true&lt;/h2&gt;
&lt;p&gt;We will start our exploration with a very inane observation. It is
essentially the observation that 1+1=2, which every child discover some
time before the age of five. As mentioned, this is the final “insight” I
had, which tied all the pieces together.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Bool ≅ Maybe ()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There it is! The equality sign with the squiggle over it means
“isomorphic” which is a fancy way of saying “is essentially the same as”
which for Haskell types mean that there are translation functions back
and forth which are mutual inverses. So, in theory, any place you use a
&lt;code&gt;Bool&lt;/code&gt; you can use a &lt;code&gt;Maybe ()&lt;/code&gt; value. Just
replace &lt;code&gt;True&lt;/code&gt; with &lt;code&gt;Just ()&lt;/code&gt; and False with
&lt;code&gt;Nothing&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Digression: &lt;strong&gt;“Well, actually…”&lt;/strong&gt; Alright, you clever
little imp! I know what you want to say. Haskell semantics is
Complicated™. And there are in fact differences between
&lt;code&gt;Bool&lt;/code&gt; and &lt;code&gt;Maybe ()&lt;/code&gt;. For instance,
&lt;code&gt;Just undefined&lt;/code&gt; does not really have a counterpart in
&lt;code&gt;Bool&lt;/code&gt;. An “isomorphism” could map it to either
&lt;code&gt;undefined :: Bool&lt;/code&gt; or &lt;code&gt;True :: Bool&lt;/code&gt;, but they
are both in a sense taken. But if your program depends on the exact
structure of non-total elements of &lt;code&gt;Bool&lt;/code&gt;, you deserve to
live in the purgatory you have created.&lt;/p&gt;
&lt;h2 id="but-why"&gt;But why?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Bool&lt;/code&gt; is a fine type. Very useful. In fact, it gets
special treatment in by the compiler. Only Bools can be used in
if-expressions and guards. So, this is not a suggestion to replace
&lt;code&gt;Bool&lt;/code&gt; with &lt;code&gt;Maybe ()&lt;/code&gt; if your program works well
with &lt;code&gt;Bool&lt;/code&gt;. The purpose is rather to recognise that some of
the things done to booleans can be done to other structures as well. And
the core of this stems from how &lt;code&gt;Maybe ()&lt;/code&gt; consists of two
parts: &lt;code&gt;Maybe&lt;/code&gt; which is an &lt;code&gt;Applicative&lt;/code&gt;,
&lt;code&gt;Alternative&lt;/code&gt; functor and &lt;code&gt;()&lt;/code&gt; which is a
(admittedly trivial) &lt;code&gt;Monoid&lt;/code&gt;. We wil now take some of the
well-known functions involving &lt;code&gt;Bool&lt;/code&gt; and bring them to this
level of generality. Then by replacing &lt;code&gt;Maybe&lt;/code&gt; and
&lt;code&gt;()&lt;/code&gt; with other &lt;code&gt;Applicative&lt;/code&gt;,
&lt;code&gt;Alternative&lt;/code&gt; functors and &lt;code&gt;Monoids&lt;/code&gt;, these
functions will find new use cases.&lt;/p&gt;
&lt;h2 id="disjunction"&gt;Disjunction&lt;/h2&gt;
&lt;p&gt;Let us start by talking about disjunction, usually conceived as
&lt;code&gt;(||) :: Bool -&amp;gt; Bool -&amp;gt; Bool&lt;/code&gt;. But there is a
typeclass called &lt;code&gt;Alternative&lt;/code&gt; with an operator
&lt;code&gt;(&amp;lt;|&amp;gt;) :: (Alternative f) =&amp;gt; f a -&amp;gt; f a -&amp;gt; f a&lt;/code&gt;
which works like disjunction when we apply it to &lt;code&gt;Maybe ()&lt;/code&gt;:
We get &lt;code&gt;Just () &amp;lt;|&amp;gt; _ = Just ()&lt;/code&gt; (true or anything is
true) and likewise &lt;code&gt;_ &amp;lt;|&amp;gt; Just () = Just ()&lt;/code&gt; and
finally &lt;code&gt;Nothing &amp;lt;|&amp;gt; Nothing = Nothing&lt;/code&gt; (False or false
is false). But the operator has many uses. For lists it is simply
concatenation, and the operator is essential when writing parsers. The
disjunctive unit (i.e. false) is called
&lt;code&gt;empty :: (Alternative f) =&amp;gt; f a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is well-trodden stuff. But I think it is nice to highlight. For
instance, if you have something where you get a lot of Maybe-values,
perhaps in a list, and you just want to pick the first just value, you
can use &lt;code&gt;or = foldr (&amp;lt;|&amp;gt;) empty&lt;/code&gt; to convert
&lt;code&gt;[Maybe a] -&amp;gt; Maybe a&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb2-1"&gt;&lt;a href="#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;or&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Foldable&lt;/span&gt; t, &lt;span class="dt"&gt;Alternative&lt;/span&gt; f) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; t (f a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;or&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;foldr&lt;/span&gt; (&lt;span class="op"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;) empty&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is clearly a generalisation of
&lt;code&gt;or :: (Foldable t) =&amp;gt; t Bool -&amp;gt; Bool&lt;/code&gt;, but it is also
a generalisation of &lt;code&gt;concat :: [[a]] -&amp;gt; [a]&lt;/code&gt;. In
&lt;code&gt;Control.Applicative&lt;/code&gt; you will find this under the name
&lt;code&gt;asum&lt;/code&gt; and it is very useful!&lt;/p&gt;
&lt;h2 id="any"&gt;&lt;code&gt;any&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;While disjunction is useful, the reason I often end up using
&lt;code&gt;or&lt;/code&gt; to flatten something of type &lt;code&gt;t (f b)&lt;/code&gt; to
&lt;code&gt;f b&lt;/code&gt; is because I first had &lt;code&gt;t a&lt;/code&gt; and a predicate
&lt;code&gt;a -&amp;gt; f b&lt;/code&gt;. So, let us combine those two steps into a
single, beautiful function:&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb3-1"&gt;&lt;a href="#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;any&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Alternative&lt;/span&gt; f, &lt;span class="dt"&gt;Foldable&lt;/span&gt; t) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; t a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f b&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;any&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="op"&gt;$&lt;/span&gt; empty) &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;foldr&lt;/span&gt; &lt;span class="op"&gt;.&lt;/span&gt; ((&lt;span class="op"&gt;&amp;lt;|&amp;gt;&lt;/span&gt;) &lt;span class="op"&gt;.&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A very simple usage of this function is to convert from any foldable
structure to any alternative functor using &lt;code&gt;any pure&lt;/code&gt;. For
instance a &lt;code&gt;x &amp;lt;- any pure (Map.lookup i m)&lt;/code&gt; in a do-block
will lookup a value in a map and rewrap it into your current monad (as
long as it is Alternative). In fact &lt;code&gt;any pure&lt;/code&gt; is a general
conversion function which can convert from any of these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Set a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Map k a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[a]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Maybe a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Either e a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;(w,a)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;to any of these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IO a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[a]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Maybe a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Either e a&lt;/code&gt; (for &lt;code&gt;e&lt;/code&gt; a Monoid)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STM a&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Parser a&lt;/code&gt; (For some reasonable &lt;code&gt;Parser&lt;/code&gt;
monad)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Apropos the last entry in that list,
&lt;code&gt;any string ["foo","bar","bat"]&lt;/code&gt; is a parser which matches
any of the words in the list. Over in ConcurrencyLand,
&lt;code&gt;any readTChan [chan0,chan1,chan2]&lt;/code&gt; will read the first value
arriving in any of the three channels.&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb4-1"&gt;&lt;a href="#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Applicative.Logic&lt;/span&gt; (any)&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Monad&lt;/span&gt; (forever)&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Concurrent&lt;/span&gt; (forkIO)&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Concurrent.STM&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Concurrent.STM.TChan&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="co"&gt;-- Create the channels&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a href="#cb4-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; chan0 &lt;span class="ot"&gt;&amp;lt;- newTChanIO ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;TChan&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a href="#cb4-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; chan1 &lt;span class="ot"&gt;&amp;lt;- newTChanIO ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;TChan&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a href="#cb4-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; chan2 &lt;span class="ot"&gt;&amp;lt;- newTChanIO ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; (&lt;span class="dt"&gt;TChan&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a href="#cb4-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a href="#cb4-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="co"&gt;-- Create a thread reading from any chan:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a href="#cb4-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; forkIO &lt;span class="op"&gt;$&lt;/span&gt; forever&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a href="#cb4-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             &lt;span class="op"&gt;$&lt;/span&gt; atomically (readTChan &lt;span class="ot"&gt;`any`&lt;/span&gt; [chan0,chan1,chan2])&lt;/span&gt;
&lt;span id="cb4-15"&gt;&lt;a href="#cb4-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-16"&gt;&lt;a href="#cb4-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;ThreadId&lt;/span&gt; &lt;span class="dv"&gt;689&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-17"&gt;&lt;a href="#cb4-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-18"&gt;&lt;a href="#cb4-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="co"&gt;-- Now we can write to any of the channels:&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-19"&gt;&lt;a href="#cb4-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; atomically &lt;span class="op"&gt;$&lt;/span&gt; writeTChan chan1 &lt;span class="st"&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-20"&gt;&lt;a href="#cb4-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Foo&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-21"&gt;&lt;a href="#cb4-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; atomically &lt;span class="op"&gt;$&lt;/span&gt; writeTChan chan0 &lt;span class="st"&gt;&amp;quot;Bar&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-22"&gt;&lt;a href="#cb4-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Bar&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-23"&gt;&lt;a href="#cb4-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ghci&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; atomically &lt;span class="op"&gt;$&lt;/span&gt; writeTChan chan2 &lt;span class="st"&gt;&amp;quot;Baz&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-24"&gt;&lt;a href="#cb4-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Baz&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The moral is that you can use this generalised &lt;code&gt;any&lt;/code&gt; in
many places where the word &lt;em&gt;any&lt;/em&gt; would fall natural to use
informally.&lt;/p&gt;
&lt;h2 id="conjunction"&gt;Conjunction&lt;/h2&gt;
&lt;p&gt;Having gone on and on about disjuntion, I should talk about
conjunction. There might some wiggle room for what notion of conjunction
best fits, but my experience from a lot of examples suggest that the
following is practical:&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb5-1"&gt;&lt;a href="#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;(&amp;amp;&amp;amp;) ::&lt;/span&gt; (&lt;span class="dt"&gt;Applicative&lt;/span&gt; f, &lt;span class="dt"&gt;Monoid&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;     &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(&lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt;) &lt;span class="ot"&gt;=&lt;/span&gt; liftA2 (&lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Why Monoid? The idea is that &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; combines two
generalised truth values. The &lt;code&gt;a&lt;/code&gt; argument to &lt;code&gt;f&lt;/code&gt;
represents evidence of truth (say, a set of solutions, or results from a
search or something). Thus, if a conjunction is true we must take into
account the evidence from both sides. One option would be to instead use
&lt;code&gt;liftA2 (,) :: f a -&amp;gt; f b -&amp;gt; f (a,b)&lt;/code&gt;, in a kind
I-know-Curry–Howard way. But that will not really generalise to a
function similar to &lt;code&gt;any&lt;/code&gt;, where we collect evidence from a
whole structure of elements. Thus, the Monoid alternative seems more
useful in practice.&lt;/p&gt;
&lt;p&gt;You can probably imagine uses for &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; yourself,
so let us get off the ground by defining &lt;code&gt;and&lt;/code&gt;:&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb6-1"&gt;&lt;a href="#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;and&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Foldable&lt;/span&gt; t, &lt;span class="dt"&gt;Applicative&lt;/span&gt; f, &lt;span class="dt"&gt;Monoid&lt;/span&gt; a)&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; t (f a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;and&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;foldr&lt;/span&gt; (&lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt;) (&lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="fu"&gt;mempty&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see &lt;code&gt;pure mempty&lt;/code&gt; is the new &lt;code&gt;True&lt;/code&gt;,
otherwise only the type signature changed from the Bool definition. But
what can we do with it? Let us start with a combinatorics example: Say
we want to generate all sentences of the form “Harry/Sue loves/hates
kale/honey”. Here is a solution:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ghci&amp;gt; all putStrLn $ and [[&amp;quot;Harry&amp;quot;,&amp;quot;Sue&amp;quot;],  [&amp;quot; &amp;quot;]
                         ,[&amp;quot;loves&amp;quot;,&amp;quot;hates&amp;quot;],[&amp;quot; &amp;quot;]
                         ,[&amp;quot;kale&amp;quot;,&amp;quot;honey&amp;quot;], [&amp;quot;.&amp;quot;]]
Harry loves kale.
Harry loves honey.
Harry hates kale.
Harry hates honey.
Sue loves kale.
Sue loves honey.
Sue hates kale.
Sue hates honey.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alright, I could not resist sneaking in an early “all”s in that. Stay
tuned for it the next subsection, but ignore it for the moment, and let
us focus on “and”. This example is standard list monad stuff, but the
&lt;code&gt;and&lt;/code&gt; function lets us easily generate combinations from
lists of alternatives.&lt;/p&gt;
&lt;h2 id="all"&gt;&lt;code&gt;all&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We have already seen one use of the generalised &lt;code&gt;all&lt;/code&gt;,
namely applying an IO function to every element of a list:
&lt;code&gt;all print [1..10]&lt;/code&gt;. But there already exists plenty of
functions doing that. Can we do something else? Just pick your
faviourite Applicative and start experimenting. Picking STM for
instance, we can wait until a moment when all channels have something
ready and get that using
&lt;code&gt;all ((singleton &amp;lt;$&amp;gt;) . readTChan) [chan0,chan1,chan2] :: STM [a]&lt;/code&gt;.
Or for &lt;code&gt;IO&lt;/code&gt; one can
&lt;code&gt;all readFile :: [FilePath] -&amp;gt; IO String&lt;/code&gt; to read list of
files into a single string.&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb8-1"&gt;&lt;a href="#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;all&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; (&lt;span class="dt"&gt;Applicative&lt;/span&gt; f, &lt;span class="dt"&gt;Monoid&lt;/span&gt; b, &lt;span class="dt"&gt;Foldable&lt;/span&gt; t)&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; t a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f b&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;all&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="fu"&gt;mempty&lt;/span&gt;) &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;foldr&lt;/span&gt; &lt;span class="op"&gt;.&lt;/span&gt; ((&lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt;) &lt;span class="op"&gt;.&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that
&lt;code&gt;guard :: (Alternative f) =&amp;gt; Bool -&amp;gt; f ()&lt;/code&gt; converts a
standard bool to an applicative truth value. Hence
&lt;code&gt;all guard :: (Alternative f, Foldable t) =&amp;gt; t Bool -&amp;gt; f ()&lt;/code&gt;
can be used where one would use &lt;code&gt;and&lt;/code&gt; normally. For instance,
here is a function which checks if a list is sorted:&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb9-1"&gt;&lt;a href="#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;ascending ::&lt;/span&gt; (&lt;span class="dt"&gt;Alternative&lt;/span&gt; f, &lt;span class="dt"&gt;Ord&lt;/span&gt; b) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; [b] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f ()&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ascending l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; guard &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;zipWith&lt;/span&gt; (&lt;span class="op"&gt;&amp;lt;=&lt;/span&gt;) l (&lt;span class="fu"&gt;tail&lt;/span&gt; l)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="extended-example"&gt;Extended example&lt;/h2&gt;
&lt;p&gt;Here is a simple example where you can see a few usages of the
applicative logic functions in context. It is simply a game of
tic-tac-toe, but it demonstrates a few usages and the general intuition
of &lt;code&gt;any&lt;/code&gt;, &lt;code&gt;or&lt;/code&gt;, &lt;code&gt;all&lt;/code&gt;, &lt;code&gt;and&lt;/code&gt;
and &lt;code&gt;convert&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb10-1"&gt;&lt;a href="#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Monad&lt;/span&gt; (guard)&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Applicative&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="#cb10-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="kw"&gt;qualified&lt;/span&gt; &lt;span class="dt"&gt;Data.Map&lt;/span&gt; &lt;span class="kw"&gt;as&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-4"&gt;&lt;a href="#cb10-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Map&lt;/span&gt; (&lt;span class="dt"&gt;Map&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-5"&gt;&lt;a href="#cb10-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Functor&lt;/span&gt; (($&amp;gt;))&lt;/span&gt;
&lt;span id="cb10-6"&gt;&lt;a href="#cb10-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-7"&gt;&lt;a href="#cb10-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;System.Random&lt;/span&gt; (randomRIO)&lt;/span&gt;
&lt;span id="cb10-8"&gt;&lt;a href="#cb10-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-9"&gt;&lt;a href="#cb10-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Prelude&lt;/span&gt; &lt;span class="kw"&gt;hiding&lt;/span&gt; (any, all, or)&lt;/span&gt;
&lt;span id="cb10-10"&gt;&lt;a href="#cb10-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Applicative.Logic&lt;/span&gt; (any, all, or, convert)&lt;/span&gt;
&lt;span id="cb10-11"&gt;&lt;a href="#cb10-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-12"&gt;&lt;a href="#cb10-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- Game data&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-13"&gt;&lt;a href="#cb10-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;X&lt;/span&gt; &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="dt"&gt;O&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-14"&gt;&lt;a href="#cb10-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;deriving&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt;,&lt;span class="dt"&gt;Show&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-15"&gt;&lt;a href="#cb10-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-16"&gt;&lt;a href="#cb10-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="dt"&gt;Integer&lt;/span&gt;,&lt;span class="dt"&gt;Integer&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-17"&gt;&lt;a href="#cb10-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-18"&gt;&lt;a href="#cb10-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Map&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-19"&gt;&lt;a href="#cb10-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-20"&gt;&lt;a href="#cb10-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;isValidMove ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-21"&gt;&lt;a href="#cb10-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;isValidMove board (x,y) &lt;span class="ot"&gt;=&lt;/span&gt;  &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; x &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-22"&gt;&lt;a href="#cb10-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; y &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-23"&gt;&lt;a href="#cb10-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="op"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="fu"&gt;null&lt;/span&gt; (Map.lookup (x,y) board)&lt;/span&gt;
&lt;span id="cb10-24"&gt;&lt;a href="#cb10-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-25"&gt;&lt;a href="#cb10-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- All positions on the board&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-26"&gt;&lt;a href="#cb10-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;allPositions ::&lt;/span&gt; [&lt;span class="dt"&gt;Position&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb10-27"&gt;&lt;a href="#cb10-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;allPositions &lt;span class="ot"&gt;=&lt;/span&gt; liftA2 (,) [&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;..&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;] [&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;..&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb10-28"&gt;&lt;a href="#cb10-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-29"&gt;&lt;a href="#cb10-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- Make a move on the board&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-30"&gt;&lt;a href="#cb10-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;move ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-31"&gt;&lt;a href="#cb10-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;move board pos m &lt;span class="ot"&gt;=&lt;/span&gt; guard (isValidMove board pos)&lt;/span&gt;
&lt;span id="cb10-32"&gt;&lt;a href="#cb10-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;$&amp;gt;&lt;/span&gt; Map.insert pos m board&lt;/span&gt;
&lt;span id="cb10-33"&gt;&lt;a href="#cb10-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-34"&gt;&lt;a href="#cb10-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- Verify who has won&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-35"&gt;&lt;a href="#cb10-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;won ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-36"&gt;&lt;a href="#cb10-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;won board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;any&lt;/span&gt; filled streaks &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-37"&gt;&lt;a href="#cb10-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;-- Generate all streaks&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-38"&gt;&lt;a href="#cb10-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    streaks &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-39"&gt;&lt;a href="#cb10-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          x &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; allPositions&lt;/span&gt;
&lt;span id="cb10-40"&gt;&lt;a href="#cb10-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          y &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;filter&lt;/span&gt; (x&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;) allPositions&lt;/span&gt;
&lt;span id="cb10-41"&gt;&lt;a href="#cb10-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          z &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;filter&lt;/span&gt; (y&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;) allPositions&lt;/span&gt;
&lt;span id="cb10-42"&gt;&lt;a href="#cb10-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          check [x,y,z]&lt;/span&gt;
&lt;span id="cb10-43"&gt;&lt;a href="#cb10-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="fu"&gt;pure&lt;/span&gt; [x,y,z]&lt;/span&gt;
&lt;span id="cb10-44"&gt;&lt;a href="#cb10-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;-- Check that three positions form a streak&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-45"&gt;&lt;a href="#cb10-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    check l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-46"&gt;&lt;a href="#cb10-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              guard (&lt;span class="fu"&gt;mod&lt;/span&gt; (&lt;span class="fu"&gt;sum&lt;/span&gt; (&lt;span class="fu"&gt;fst&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l)) &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-47"&gt;&lt;a href="#cb10-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              guard (&lt;span class="fu"&gt;mod&lt;/span&gt; (&lt;span class="fu"&gt;sum&lt;/span&gt; (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l)) &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-48"&gt;&lt;a href="#cb10-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ascending (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l) &lt;span class="op"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; decending (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l)&lt;/span&gt;
&lt;span id="cb10-49"&gt;&lt;a href="#cb10-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;-- Verify that a player has filled a streak&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-50"&gt;&lt;a href="#cb10-50" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    filled streak &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-51"&gt;&lt;a href="#cb10-51" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        marks &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;traverse&lt;/span&gt; (&lt;span class="ot"&gt;`Map.lookup`&lt;/span&gt; board) streak&lt;/span&gt;
&lt;span id="cb10-52"&gt;&lt;a href="#cb10-52" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        m &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;any&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; marks&lt;/span&gt;
&lt;span id="cb10-53"&gt;&lt;a href="#cb10-53" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="fu"&gt;all&lt;/span&gt; (guard &lt;span class="op"&gt;.&lt;/span&gt; (&lt;span class="op"&gt;==&lt;/span&gt;m)) marks&lt;/span&gt;
&lt;span id="cb10-54"&gt;&lt;a href="#cb10-54" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="fu"&gt;pure&lt;/span&gt; m&lt;/span&gt;
&lt;span id="cb10-55"&gt;&lt;a href="#cb10-55" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;-- Utility functions&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-56"&gt;&lt;a href="#cb10-56" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ascending l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; guard &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;zipWith&lt;/span&gt; (&lt;span class="op"&gt;&amp;lt;=&lt;/span&gt;) l (&lt;span class="fu"&gt;tail&lt;/span&gt; l)&lt;/span&gt;
&lt;span id="cb10-57"&gt;&lt;a href="#cb10-57" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    decending l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; guard &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;zipWith&lt;/span&gt; (&lt;span class="op"&gt;&amp;gt;=&lt;/span&gt;) l (&lt;span class="fu"&gt;tail&lt;/span&gt; l)&lt;/span&gt;
&lt;span id="cb10-58"&gt;&lt;a href="#cb10-58" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-59"&gt;&lt;a href="#cb10-59" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;-- Game playing logic&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-60"&gt;&lt;a href="#cb10-60" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-61"&gt;&lt;a href="#cb10-61" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;main ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb10-62"&gt;&lt;a href="#cb10-62" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;main &lt;span class="ot"&gt;=&lt;/span&gt; gameLoop &lt;span class="dt"&gt;X&lt;/span&gt; (Map.empty&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-63"&gt;&lt;a href="#cb10-63" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-64"&gt;&lt;a href="#cb10-64" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;gameLoop ::&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb10-65"&gt;&lt;a href="#cb10-65" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;gameLoop currentMark board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-66"&gt;&lt;a href="#cb10-66" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Current board:&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-67"&gt;&lt;a href="#cb10-67" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    printBoard board&lt;/span&gt;
&lt;span id="cb10-68"&gt;&lt;a href="#cb10-68" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;or&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-69"&gt;&lt;a href="#cb10-69" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      [ &lt;span class="kw"&gt;do&lt;/span&gt; mark &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; convert (won board)&lt;/span&gt;
&lt;span id="cb10-70"&gt;&lt;a href="#cb10-70" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Player &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; mark &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; wins!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-71"&gt;&lt;a href="#cb10-71" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , guard (Map.size board &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;9&lt;/span&gt;) &lt;span class="op"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;It&amp;#39;s a draw!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-72"&gt;&lt;a href="#cb10-72" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , guard (currentMark &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dt"&gt;X&lt;/span&gt;)    &lt;span class="op"&gt;*&amp;gt;&lt;/span&gt; moveIO board &lt;span class="dt"&gt;X&lt;/span&gt; userMove&lt;/span&gt;
&lt;span id="cb10-73"&gt;&lt;a href="#cb10-73" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                   &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; gameLoop &lt;span class="dt"&gt;O&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-74"&gt;&lt;a href="#cb10-74" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , guard (currentMark &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dt"&gt;O&lt;/span&gt;)    &lt;span class="op"&gt;*&amp;gt;&lt;/span&gt; moveIO board &lt;span class="dt"&gt;O&lt;/span&gt; computerMove&lt;/span&gt;
&lt;span id="cb10-75"&gt;&lt;a href="#cb10-75" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                   &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; gameLoop &lt;span class="dt"&gt;X&lt;/span&gt; ]&lt;/span&gt;
&lt;span id="cb10-76"&gt;&lt;a href="#cb10-76" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-77"&gt;&lt;a href="#cb10-77" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;moveIO ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-78"&gt;&lt;a href="#cb10-78" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;moveIO board mark play &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-79"&gt;&lt;a href="#cb10-79" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   pos &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; play board&lt;/span&gt;
&lt;span id="cb10-80"&gt;&lt;a href="#cb10-80" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   convert (move board pos mark)&lt;/span&gt;
&lt;span id="cb10-81"&gt;&lt;a href="#cb10-81" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="op"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; (&lt;span class="kw"&gt;do&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Position not in range!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-82"&gt;&lt;a href="#cb10-82" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               moveIO board mark play)&lt;/span&gt;
&lt;span id="cb10-83"&gt;&lt;a href="#cb10-83" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-84"&gt;&lt;a href="#cb10-84" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;userMove ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-85"&gt;&lt;a href="#cb10-85" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;userMove board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-86"&gt;&lt;a href="#cb10-86" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Enter your move (row column):&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-87"&gt;&lt;a href="#cb10-87" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    input &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;getLine&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-88"&gt;&lt;a href="#cb10-88" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;case&lt;/span&gt; &lt;span class="fu"&gt;words&lt;/span&gt; input &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span class="ot"&gt; reads ::&lt;/span&gt; [(&lt;span class="dt"&gt;Integer&lt;/span&gt;,&lt;span class="dt"&gt;String&lt;/span&gt;)] &lt;span class="kw"&gt;of&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-89"&gt;&lt;a href="#cb10-89" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       [(x,&lt;span class="st"&gt;&amp;quot;&amp;quot;&lt;/span&gt;),(y,&lt;span class="st"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; (x,y)&lt;/span&gt;
&lt;span id="cb10-90"&gt;&lt;a href="#cb10-90" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       _ &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-91"&gt;&lt;a href="#cb10-91" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Invalid input, please use the format &amp;#39;row column&amp;#39;.&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-92"&gt;&lt;a href="#cb10-92" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              userMove board&lt;/span&gt;
&lt;span id="cb10-93"&gt;&lt;a href="#cb10-93" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-94"&gt;&lt;a href="#cb10-94" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;randomValidMove ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-95"&gt;&lt;a href="#cb10-95" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;randomValidMove board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-96"&gt;&lt;a href="#cb10-96" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;let&lt;/span&gt; validMoves &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;filter&lt;/span&gt; (isValidMove board) allPositions&lt;/span&gt;
&lt;span id="cb10-97"&gt;&lt;a href="#cb10-97" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    idx &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; randomRIO (&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="fu"&gt;length&lt;/span&gt; validMoves &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb10-98"&gt;&lt;a href="#cb10-98" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; validMoves &lt;span class="op"&gt;!!&lt;/span&gt; idx&lt;/span&gt;
&lt;span id="cb10-99"&gt;&lt;a href="#cb10-99" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-100"&gt;&lt;a href="#cb10-100" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;computerMove ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-101"&gt;&lt;a href="#cb10-101" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;computerMove board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-102"&gt;&lt;a href="#cb10-102" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pos &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; randomValidMove board&lt;/span&gt;
&lt;span id="cb10-103"&gt;&lt;a href="#cb10-103" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Computer places &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; &lt;span class="dt"&gt;O&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; at &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; pos&lt;/span&gt;
&lt;span id="cb10-104"&gt;&lt;a href="#cb10-104" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; pos&lt;/span&gt;
&lt;span id="cb10-105"&gt;&lt;a href="#cb10-105" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-106"&gt;&lt;a href="#cb10-106" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;printBoard ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb10-107"&gt;&lt;a href="#cb10-107" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;printBoard board&lt;/span&gt;
&lt;span id="cb10-108"&gt;&lt;a href="#cb10-108" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; [ &lt;span class="fu"&gt;unwords&lt;/span&gt; [ &lt;span class="fu"&gt;maybe&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-109"&gt;&lt;a href="#cb10-109" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                   &lt;span class="op"&gt;$&lt;/span&gt; Map.lookup (x,y) board&lt;/span&gt;
&lt;span id="cb10-110"&gt;&lt;a href="#cb10-110" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   &lt;span class="op"&gt;|&lt;/span&gt; y &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; [&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;..&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb10-111"&gt;&lt;a href="#cb10-111" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   &lt;span class="op"&gt;|&lt;/span&gt; x &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; [&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;..&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="highlights-of-the-extended-example"&gt;Highlights of the extended
example&lt;/h3&gt;
&lt;p&gt;Let me highlight a few usages of applicative logical function in the
above code. The first and most striking part is the
check-if-board-is-won function:&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb11-1"&gt;&lt;a href="#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;won ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="#cb11-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;won board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;any&lt;/span&gt; filled streaks&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This uses &lt;code&gt;Maybe Mark&lt;/code&gt; as a proof-relevant truth value for
&lt;code&gt;any&lt;/code&gt;. Instead of just &lt;code&gt;True&lt;/code&gt; when the board is
won we get &lt;code&gt;Just X&lt;/code&gt; or &lt;code&gt;Just O&lt;/code&gt;, depending on
which player won. And the code simply says that the board is won if
there are any filled streaks (of three board positions in a row).&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb12-1"&gt;&lt;a href="#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;filled ::&lt;/span&gt; [&lt;span class="dt"&gt;Position&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filled streak &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    marks &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;traverse&lt;/span&gt; (&lt;span class="ot"&gt;`Map.lookup`&lt;/span&gt; board) streak&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    m &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;any&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; marks&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;all&lt;/span&gt; (guard &lt;span class="op"&gt;.&lt;/span&gt; (&lt;span class="op"&gt;==&lt;/span&gt;m)) marks&lt;/span&gt;
&lt;span id="cb12-6"&gt;&lt;a href="#cb12-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;pure&lt;/span&gt; m&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;filled&lt;/code&gt; function uses both &lt;code&gt;any&lt;/code&gt; and
&lt;code&gt;and&lt;/code&gt; to check that a list of board possitions are filled
with the same mark. First it uses &lt;code&gt;traverse&lt;/code&gt; to check that
all the positions of &lt;code&gt;streak&lt;/code&gt; are filled with something on
the current boar and collects them in a list. Then
&lt;code&gt;m &amp;lt;- any pure marks&lt;/code&gt; picks out the first mark of the
streak and &lt;code&gt;all (guard . (==m)) marks&lt;/code&gt; verifies that the
remaining marks of the streak are all the same.&lt;/p&gt;
&lt;p&gt;While it does not use any of the applicative logic functions
directly, the code for generating all streaks is a nice example of
thinking of applicative values as propositions:&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb13-1"&gt;&lt;a href="#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;streaks ::&lt;/span&gt; [[&lt;span class="dt"&gt;Position&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;streaks &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        x &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; allPositions&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        y &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;filter&lt;/span&gt; (x&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;) allPositions&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        z &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="fu"&gt;filter&lt;/span&gt; (y&lt;span class="op"&gt;&amp;lt;&lt;/span&gt;) allPositions&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        check [x,y,z]&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="fu"&gt;pure&lt;/span&gt; [x,y,z]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This all happens in do-syntax for lists, and the first three lines
are self-explanatory. The &lt;code&gt;check&lt;/code&gt; function however is a
predicate which checks if three positions form a streak (are in a row on
the board). It is converted from &lt;code&gt;Bool&lt;/code&gt; with heavy usage of
guards:&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb14-1"&gt;&lt;a href="#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;check l &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            guard (&lt;span class="fu"&gt;mod&lt;/span&gt; (&lt;span class="fu"&gt;sum&lt;/span&gt; (&lt;span class="fu"&gt;fst&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l)) &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            guard (&lt;span class="fu"&gt;mod&lt;/span&gt; (&lt;span class="fu"&gt;sum&lt;/span&gt; (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l)) &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb14-4"&gt;&lt;a href="#cb14-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ascending (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l) &lt;span class="op"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; decending (&lt;span class="fu"&gt;snd&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; l)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Over in the IO part of the program, there is an interesting
pattern:&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb15-1"&gt;&lt;a href="#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;gameLoop ::&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;gameLoop currentMark board &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Current board:&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    printBoard board&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fu"&gt;or&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-6"&gt;&lt;a href="#cb15-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      [ &lt;span class="kw"&gt;do&lt;/span&gt; mark &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; convert (won board)&lt;/span&gt;
&lt;span id="cb15-7"&gt;&lt;a href="#cb15-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Player &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; mark &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; wins!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-8"&gt;&lt;a href="#cb15-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , guard (Map.size board &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;9&lt;/span&gt;) &lt;span class="op"&gt;*&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;It&amp;#39;s a draw!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-9"&gt;&lt;a href="#cb15-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , guard (currentMark &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dt"&gt;X&lt;/span&gt;)    &lt;span class="op"&gt;*&amp;gt;&lt;/span&gt; moveIO board &lt;span class="dt"&gt;X&lt;/span&gt; userMove&lt;/span&gt;
&lt;span id="cb15-10"&gt;&lt;a href="#cb15-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                   &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; gameLoop &lt;span class="dt"&gt;O&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-11"&gt;&lt;a href="#cb15-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      , guard (currentMark &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dt"&gt;O&lt;/span&gt;)    &lt;span class="op"&gt;*&amp;gt;&lt;/span&gt; moveIO board &lt;span class="dt"&gt;O&lt;/span&gt; computerMove&lt;/span&gt;
&lt;span id="cb15-12"&gt;&lt;a href="#cb15-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                   &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; gameLoop &lt;span class="dt"&gt;X&lt;/span&gt; ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I am not sure this is actually a sane way do conditionals in
&lt;code&gt;IO&lt;/code&gt;, but it works. The &lt;code&gt;or [⋯]&lt;/code&gt; part is
interesting because it attempts to execute the elements of the list in
order and stops once one of the steps succeeds. So, for instance:&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb16-1"&gt;&lt;a href="#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;do&lt;/span&gt; mark &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; convert (won board)&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Player &amp;quot;&lt;/span&gt; &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt; mark &lt;span class="op"&gt;++&lt;/span&gt; &lt;span class="st"&gt;&amp;quot; wins!&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Will fail if no player has won yet. The
&lt;code&gt;Applicative.Logic.convert&lt;/code&gt; function converts the
&lt;code&gt;Maybe Mark&lt;/code&gt; into &lt;code&gt;IO Mark&lt;/code&gt;, throwing an exception
on &lt;code&gt;Nothing&lt;/code&gt;, so the &lt;code&gt;putStrLn&lt;/code&gt; part will only run
if someone actually won. Otherwise, it will continue with checking for a
draw, or letting one of the players move.&lt;/p&gt;
&lt;p&gt;The
&lt;code&gt;move :: Board -&amp;gt; Position -&amp;gt; Mark -&amp;gt; Maybe Board&lt;/code&gt;
function integrates the check of validity with the updating of the
board. In the IO part again we use &lt;code&gt;convert&lt;/code&gt; (aka
&lt;code&gt;any pure&lt;/code&gt;) to get an &lt;code&gt;IO&lt;/code&gt; value of the updated
board, and use disjunction for error handling:&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb17-1"&gt;&lt;a href="#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;moveIO ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Mark&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Position&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;moveIO board mark play &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-3"&gt;&lt;a href="#cb17-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   pos &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; play board&lt;/span&gt;
&lt;span id="cb17-4"&gt;&lt;a href="#cb17-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   convert (move board pos mark)&lt;/span&gt;
&lt;span id="cb17-5"&gt;&lt;a href="#cb17-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       &lt;span class="op"&gt;&amp;lt;|&amp;gt;&lt;/span&gt; (&lt;span class="kw"&gt;do&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;Position not in range!&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-6"&gt;&lt;a href="#cb17-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               moveIO board mark play)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The final little bit of niceness is to use &lt;code&gt;all&lt;/code&gt; instead
of &lt;code&gt;mapM_&lt;/code&gt; to print each row of the board on a separate
line:&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre
class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb18-1"&gt;&lt;a href="#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;printBoard ::&lt;/span&gt; &lt;span class="dt"&gt;Board&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;printBoard board&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;all&lt;/span&gt; &lt;span class="fu"&gt;putStrLn&lt;/span&gt; [ &lt;span class="fu"&gt;unwords&lt;/span&gt; [ &lt;span class="fu"&gt;maybe&lt;/span&gt; &lt;span class="st"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; &lt;span class="fu"&gt;show&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="#cb18-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                   &lt;span class="op"&gt;$&lt;/span&gt; Map.lookup (x,y) board&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="#cb18-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   &lt;span class="op"&gt;|&lt;/span&gt; y &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; [&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;..&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb18-6"&gt;&lt;a href="#cb18-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   &lt;span class="op"&gt;|&lt;/span&gt; x &lt;span class="ot"&gt;&amp;lt;-&lt;/span&gt; [&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="op"&gt;..&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/tutorials/basic-website.html</id>
    <title>Setting up a basic website</title>
    <updated>2022-05-17T12:00:00Z</updated>
    <published>2022-05-17T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/tutorials/basic-website.html"/>
    <content type="html">&lt;p&gt;There are lot of different ways to make a website. You can write your
own &lt;a href="https://en.wikipedia.org/wiki/HTML"&gt;HTML code&lt;/a&gt; (the code
your web-browser reads when it draws a webpage), use a &lt;a
href="http://en.wikipedia.org/wiki/WYSIWYG"&gt;WYSIWYG&lt;/a&gt; editor or
install Wordpress… This guide is for those who wish to focus on the
textual content of their site, and keep the number of distractions down.
The following are the key points, each of which might warrant further
explainations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep the barrier for writing and editing the webpages low.&lt;/li&gt;
&lt;li&gt;Do the editing on a local machine.&lt;/li&gt;
&lt;li&gt;Make it easy to deploy changes to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now let us discuss the technical tools I have chosen to implement
these key points. They are each in them selves quite simple, but might
take a bit of effort to get comfortable with&lt;a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.
Here is the list.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write the content in Markdown.&lt;/li&gt;
&lt;li&gt;Use a version control system such as darcs.&lt;/li&gt;
&lt;li&gt;Automate your operations using mk or make.&lt;/li&gt;
&lt;li&gt;Mount the server file system locally using sshfs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will go through all these. At the end there is a worked &lt;a
href="#example"&gt;example&lt;/a&gt;, and a &lt;a href="#discussion"&gt;discussion&lt;/a&gt;.
Before you get started, you need some hosting for your web page. If you
can have a machine running at all times, I recommend hosting your own
web site, but any hosting which allows you to upload simple html files
will work for this tutorial.&lt;/p&gt;
&lt;h2 id="markdown-and-pandoc"&gt;Markdown and Pandoc&lt;/h2&gt;
&lt;p&gt;Writing your own &lt;a href="http://en.wikipedia.org/wiki/HTML/"&gt;HTML
code&lt;/a&gt; need not be very stressful, and gives complete flexibility —
but with this flexibility comes distractions. If you are a perfectionist
you easily get caught up in the struggle of making your page look
perfect on every browser. HTML is growing bigger and bigger with new
standards popping up every year. &lt;a
href="http://pandoc.org/demo/example9/pandocs-markdown.html"&gt;Markdown&lt;/a&gt;
however lets you write your page in a text file, and just slightly hint
at the markup — using newlines to separate paragraphs, and #s to mark
headings, for example. After writing the text you can convert the file
to HTML and put it online.&lt;/p&gt;
&lt;p&gt;You can use any text editor to write your markdown files. I recommend
any text editor which allows you to write without too many distractions.
This page was written in &lt;a
href="http://doc.cat-v.org/plan_9/4th_edition/papers/acme/"&gt;Acme&lt;/a&gt;
from &lt;a href="https://swtch.com/plan9port/"&gt;Plan9Port&lt;/a&gt; on Linux.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://pandoc.org/"&gt;Pandoc&lt;/a&gt; is the document format
swiss-army knife. It converts text documents between a lot of formats,
including Markdown and HTML. This document is written in Markdown, but
you are reading it as a HTML page. The following command was used to
convert it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pandoc --standalone --smart -T &amp;#39;&amp;#39; -f markdown -t html5 --css /markdown.css\
 -o tutorials/basic-website.html tutorials/basic-website&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;--standalone&lt;/code&gt; gives the html file a header, so that
it can stand on its own. The &lt;code&gt;--smart&lt;/code&gt; tag corrects some
typographical quirks. Finally the &lt;code&gt;-T ''&lt;/code&gt; gives the page an
automatic title header. As you can see from the command, I have
specified a custom css file to be used. The &lt;a
href="http://en.wikipedia.org/wiki/CSS/"&gt;CSS&lt;/a&gt; file I use for Markdown
can be found &lt;a href="../markdown.css"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="darcs"&gt;Darcs&lt;/h2&gt;
&lt;p&gt;A &lt;em&gt;version control&lt;/em&gt; system is a program which keeps track of a
collection of files and revisions there of. Typically all versions
previous versions are preserved, so that you can go back to an earlier
revision, or keep update several, independent versions of your files&lt;a
href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Use a version contol system. I recomend &lt;a
href="http://darcs.net/"&gt;darcs&lt;/a&gt;, but there are other alternatives. A
quick introduction to darcs is found &lt;a href="darcs.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the purpose of making a web-page the advantage of using a version
control system is that one can keep track of all revisions one made.
Also, being able to have separate branches means that you can work on
bigger changes while at the same time keeping the old version up to
date. It also allows undoing changes more easily and cleanly.&lt;/p&gt;
&lt;p&gt;One can of course setup a darcs repository where the site is deployed
to. This has the advantage of being able to use “darcs push” to update
the web-page. There are a couple of reasons why I do not do it this way.
The most basic one is that since it is really just the generated HTML we
need to put on the server and revision control is only needed for the
Markdown-files, we might as well just copy the HTML-files once they are
generated.&lt;/p&gt;
&lt;h2 id="mk"&gt;mk&lt;/h2&gt;
&lt;p&gt;Once you have started writing your website you might get tired of
typing that long &lt;code&gt;pandoc&lt;/code&gt; command every time. Also, you might
grow tired of copying the HTML files to the server every time you made a
minor edit. This is when writing a mkfile (or makefile) is useful. A
mkfile contains the commands needed to build a given set of files. Once
the mkfile is written, you call on the command &lt;code&gt;mk&lt;/code&gt; to build
them.&lt;/p&gt;
&lt;p&gt;I have written a small mkfile which takes care of these things. It
uses the &lt;a href="https://swtch.com/plan9port/"&gt;Plan 9 from User
Space&lt;/a&gt; userland (&lt;code&gt;rc&lt;/code&gt; and &lt;code&gt;mk&lt;/code&gt; to be precise),
so be sure to have those installed.&lt;/p&gt;
&lt;p&gt;It depends on having a file called &lt;code&gt;deployment-index&lt;/code&gt;
which lists all the HTML- and CSS files and all directories you want to
deploy. Just write a list of the files and make sure that directories
end with &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is my &lt;code&gt;mkfile&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MKSHELL=$PLAN9/bin/rc

# This names a file which we read as index.
index=&amp;#39;deployment-index&amp;#39;

# Generate HTML-files from markdown

%.html: %
   pandoc --standalone --smart -T &amp;#39;&amp;#39; -f markdown\
    -t html5 --css /markdown.css -o $stem.html $stem

# Virtual targets

all:QV: `{grep -v &amp;#39;/$&amp;#39; $index}
    

# Deploy all files in $index to $destination

deploy:QV: `{grep -v &amp;#39;/$&amp;#39; $index}
  for (f in `{grep &amp;#39;/$&amp;#39; $index})
    mkdir $destination/$f &amp;gt;[2] /dev/null \
     || echo $destination/$f exists. Omitting .
  for(i in `{grep -v &amp;#39;/$&amp;#39; $index})
    cp -v $i $destination/$i&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mk deploy &amp;#39;destination=/path/to/deployed-site&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will deploy all the files in &lt;code&gt;deployment-index&lt;/code&gt; to
&lt;code&gt;/path/to/deployed-site&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="sshfs"&gt;sshfs&lt;/h2&gt;
&lt;p&gt;When deploying the site can be useful to mount the server using &lt;a
href="http://fuse.sourceforge.net/sshfs.html"&gt;sshfs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="rsync"&gt;rsync&lt;/h2&gt;
&lt;p&gt;Alternatively, you can use &lt;code&gt;rsync(1)&lt;/code&gt; to copy the files to
a remote server. The following mk rule assumes you have set the host and
destination enviromentvariables:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
rsyncdeploy:QV: all
  time -f &amp;#39;Total deployment time: %e seconds&amp;#39; rc -c &amp;#39;
    build=`{mktemp}
    destination=$build mk deploy
    echo &amp;#39;&amp;#39;Synchronising remote copy.&amp;#39;&amp;#39;
    rsync -rcvz $build/ $host:$destination
    echo &amp;#39;&amp;#39;Removing local copy.&amp;#39;&amp;#39;
    rm -r $build&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="a-word-on-backup"&gt;A word on backup&lt;/h2&gt;
&lt;p&gt;Keep backups of your files! Use an online service or keep your own
backup disks. If you loose the markdown files, you can convert the HTML
files back to markdown, but you will loose earlier revisions, and
work-in-process. If the host of your web-site has some space for you
which do not end up on the internet, it might be a good place to keep
the backup.&lt;/p&gt;
&lt;p&gt;Having our files managed by Darcs makes it easy to push the current
state to a backup — so there are no excuses for not making frequent
backups.&lt;/p&gt;
&lt;h2 id="extra-credits"&gt;Extra credits&lt;/h2&gt;
&lt;h3 id="test-suite"&gt;Test suite&lt;/h3&gt;
&lt;p&gt;One thing you can do for extra credits is to add a test suite to your
web-page. We do not have any «dynamic content» or fancy programming on
the web page, so a test suite might sound unnessesairy. However, you
could make a test suite looking for anti-patterns in your writing. Or
maybe you want to spell check your writing before publishing?&lt;/p&gt;
&lt;p&gt;As a useful example, the following mk rule will look for dead
links:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;links-check:QV: `{grep -v &amp;#39;/$&amp;#39; $index | grep &amp;#39;\.html$&amp;#39;}
  if (~ $base &amp;#39;&amp;#39;)
     base=`{pwd}
# Get the absolute path for base
  wd=`{pwd}
  cd $base
  base=`{pwd}
  cd $wd
# Get the search and replace string for absolute server links
  ss=&amp;#39;s/^\//&amp;#39;`{echo $base | ssam -e &amp;#39;s/\//\\\//g&amp;#39;}^&amp;#39;\//g&amp;#39;
# Iterate through html files and check remote links with curl
  for(i in `{grep -v &amp;#39;/$&amp;#39; $index | grep &amp;#39;\.html$&amp;#39;}) {
     cd $base
     newdir=`{echo $i | ssam -e &amp;#39;x/[^\/]*$/ d&amp;#39;}
     if (! ~ $newdir &amp;#39;&amp;#39;)
        cd $newdir
     for (u in `{ssam -e &amp;#39;y/href\=\&amp;quot;[^&amp;quot;]*\&amp;quot;/ d&amp;#39; &amp;lt; $base/$i \
               | ssam -e &amp;#39;x/href=/ d&amp;#39; \
	       | ssam -e &amp;#39;x/\&amp;quot;[^\&amp;quot;]*\&amp;quot;/ y/[^\&amp;quot;]*/ c/\n/&amp;#39; \
	       | grep -v &amp;#39;^$&amp;#39; | grep -v &amp;#39;^#&amp;#39; | grep -o &amp;#39;^[^#]*&amp;#39; \
	       | ssam -e $ss } ) {
        if (! test -e $u)
           if (! curl -k -s -r 0-255 -o /dev/null $u) {
              echo $u is invalid in $i
              cd $base
              exit 1}
         }
     cd $base }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Darcs can be made aware that we have tests we want to perform by
running the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; % darcs setpref test &amp;#39;mk links-check&amp;#39;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Exercise:&lt;/em&gt; Add a test which checks spelling of documents.&lt;/p&gt;
&lt;h3 id="generating-other-formats"&gt;Generating other formats&lt;/h3&gt;
&lt;p&gt;Pandoc can generate many formats. One of the formats it generates is
&lt;a href="https://en.wikipedia.org/wiki/LaTeX"&gt;Latex&lt;/a&gt;, a powerful
document markup language, from which we can generate PDFs. Assuming you
have a LaTeX distribution installed, extending the mkfile with the
following lines will add PDF-targets.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Generate PDF-files via tex files.

TEXINPUTS=.:`{grep &amp;#39;/$&amp;#39; $index \
  | ssam -e &amp;#39;x/\n/ c/:/&amp;#39; }

%.tex: %
   pandoc --standalone --smart -T &amp;#39;&amp;#39; -f markdown\
    -t latex -o $stem.tex $stem

%.pdf: %.tex
   pdflatex -output-directory `{echo $stem |\
    ssam &amp;#39;x/\/[^\/]*$/ d&amp;#39;} $stem.tex&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Just &lt;code&gt;mk your-file.pdf&lt;/code&gt; and a PDF-file will be constructed
from the &lt;code&gt;your-file&lt;/code&gt; markdown. Remember to add the pdf to the
deployment index!&lt;/p&gt;
&lt;p&gt;You can read this tutorial as a PDF &lt;a
href="basic-website.pdf"&gt;here&lt;/a&gt; — it was generated in the way outlined
above.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exercise:&lt;/em&gt; Read the pandoc documentation, find another useful
format to convert a webpage to and add an mk-target for it.&lt;/p&gt;
&lt;h2 id="disussion"&gt;Disussion&lt;/h2&gt;
&lt;p&gt;This above technique will produce a website which might strike the
reader as a primitive web page — limited in its technical abilities
compared to the modern interactive ideals in which every page at least
has a comment section. This guide is to be to taken as the tiniest grain
of sand, put on the other side of the scale — my tiny contribution to
the counter-weight of this ideal.&lt;/p&gt;
&lt;p&gt;Why do I believe such a counter-weight is needed? It is not because I
think that user-interaction is not valuable. If webpages can facilitate
fruitful discussions between people who would otherwise remain
unconfronted with each other it contributes something valuable to the
world. However, contributions by the user is always at the mercy of the
administrator and the moderator. What can appear as a free discussion is
in reality only as free as the moderator is benevolent. In the best case
the moderator is the same as the website author, whose agenda is
transparent — at the worst it is a corporation or the state. The worst
case seems by far the most common, as many sites, such as blogs,
Facebook pages and Twitter accounts, are hosted as ready-made services,
where the author is merely a slightly priviledged user.&lt;/p&gt;
&lt;p&gt;A simple website, such as one constructed in the manner described
here, can even be hosted on an outdated home computer. To censor it
would involve blocking Internet access or physically confiscate the
computer, an effort much bigger than the button-click of a moderator of
Facebook. Not to mention that it can be restored by simply moving to a
new host, given that a backup is availble.&lt;/p&gt;
&lt;p&gt;A page without a «like counter» is also not susceptible to the
tyranny of the local majority we see so many places. On say, &lt;a
href="http://en.wikipedia.org/wiki/Reddit/"&gt;Reddit&lt;/a&gt;, your
«contribution» is immediately evaluated by other users. The resulting
grade colours the way the reader receives your words — the resulting
fragmentation into cliques clearly expected by the founders by the
facility of «sub-reddits».&lt;/p&gt;
&lt;p&gt;The central tension of a dynamic discussion forum is the need for
moderators (lest the site becomes infected by spam) and the need for
freedom from moderators (lest the site becomes infected by moderator
power games and censorship).&lt;/p&gt;
&lt;p&gt;How then to facilitate discussion, if not by atomated discussion
services? My guess is that a partial solution to this question lies in
the realisation that what is called a «static webpage» (for lack of
«dynamic» content), need not be static in the real sense of the word, as
it can be changed by the owner — and new content and pages may be added.
If making your own site is simple, each can have his own to publish his
arguments to a discussion. Links between sites enables the reader to
pass from one side of the argument to the other.&lt;/p&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document"
role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;I work a lot with the command line, which for many
people seems like an odd instrument from a forgotten past, but it has
the advantage that I can completely write down my actions, which would
be impossible if I used some graphical application.&lt;a href="#fnref1"
class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2"&gt;&lt;p&gt;Or, rather, several &lt;em&gt;dependent&lt;/em&gt; versions of your
files — since darcs makes it easy to selectively import changes from one
version to another — which is far more useful.&lt;a href="#fnref2"
class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/review/mother-32.html</id>
    <title>Moog Mother-32</title>
    <updated>2019-04-01T12:00:00Z</updated>
    <published>2019-04-01T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/review/mother-32.html"/>
    <content type="html">&lt;p&gt;While I was in Stockholm giving a talk before Easter, I bought my
first analogue synthesiser: &lt;a
href="https://www.moogmusic.com/products/mother-32"&gt;a Moog
Mother-32&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="/img/mother-32-scaled.jpg"
alt="Moog Mother-32 [higher-res]" /&gt;
&lt;figcaption aria-hidden="true"&gt;Moog Mother-32 [&lt;a
href="/img/mother-32.png"&gt;higher-res&lt;/a&gt;]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Until recently I thought I would save up a bit (eh, a lot) more money
and buy a fully modular synth, but then just before going to Stockholm I
decided to bet on a semi-modular instead. Thus, I wanted to write down
my initial conclusions about that decision after playing with thing for
a few days.&lt;/p&gt;
&lt;h4 id="what-is-it"&gt;What is it?&lt;/h4&gt;
&lt;p&gt;The Mother-32 is a semi-modular analogue syntesiser. “A what?”, you
say. Well, in short (skip this if you know, or do not care, how a
synthesiser works):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Synthesiser&lt;/strong&gt; – it synthesises sound. It generates
electric signals which you can send to speakers (or head phones), so
that they will make &lt;em&gt;sound&lt;/em&gt;. The process of generating is by
feeding signals through various &lt;em&gt;components&lt;/em&gt; of the synthesiser.
Each component has various parameters which can be controlled to
generate different sounds. Here are some components of the Mother-32:
&lt;ul&gt;
&lt;li&gt;Oscillator: Generates signal (square or saw-tooth waves) with
varying frequency. Since the oscillator is controlled by an electic
signal, it is called a voltage-controlled oscillator (VCO).&lt;/li&gt;
&lt;li&gt;Filter: Dampens the signal’s content of frequencies above or below a
certain &lt;em&gt;cut-off&lt;/em&gt; frequency.&lt;/li&gt;
&lt;li&gt;Envelope generator: Generates the volume shape of individual notes.
A note does not have constant volume, but rather starts, low goes up to
a high, then descends again. The steepness of the going-up and the
going-down are called &lt;em&gt;attack&lt;/em&gt; and &lt;em&gt;decay&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Low-frequency oscillator (LFO): A second oscillator with a lower
frequency range. Can be used to modulate the parameters of other
components, or as a second sound source.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analogue synthesiser&lt;/strong&gt; – the sound is transmitted as
an analogue signal (not digital) through the components. In particular
the oscillator is an analogue electronic component.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semi-modular synthesiser&lt;/strong&gt; – While some of the
components are hard-wired to each other, there are patch points (mono
mini-jack connectors) where the user can connect inputs to outputs in
new ways. The Mother has thirty-two patch points (visible on the left
side of the picture above).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="does-it-sound-good"&gt;Does it sound good?&lt;/h4&gt;
&lt;p&gt;Yes! The sound is really above expectations. While it might look like
a cute little machine it produces really powerful sounds. Especially is
has some beautiful bass sounds easily available by just playing with the
knobs. And you find easily recognisable transitions, such as slowly
opening the filter, by fiddling the knobs.&lt;/p&gt;
&lt;p&gt;Ofcourse it matters what kind of speakers or head-set you connect it
to. The first time I connected it to my stereo I was awestruck by the
awesomeness. Also, if your stereo has an equaliser or even just a
low-pass filter (labeled “bass” in many cases), it can be used as an
extension of the instrument.&lt;/p&gt;
&lt;p&gt;A straight forward patch sounds can reasonable on all eight octaves,
but I find that most complicated configurations have a range about three
to five octaves where they sound pleasant. If you go outside that range
some of the musicality is lost.&lt;/p&gt;
&lt;h4 id="is-it-fun"&gt;Is it fun?&lt;/h4&gt;
&lt;p&gt;My biggest fear before buying the Mother-32 was that it would be no
fun. Before this I have been playing with software modular synth, and
usually my patches begin with putting up three different VCOs with a
quantiser each and start feeding them signals from an array of at least
four LFOs. So I was afraid that I would just not be able to produce
anything interesting on this single VCO single LFO thingie.&lt;/p&gt;
&lt;p&gt;However, the Mother proved my fears unfounded, I have been having a
blast playing it so far. The limitations are definitely there , but
there are both less and more possibilities than I imagined. And the
result is that I am having a lot of fun exploring the space of sounds on
the Mother.&lt;/p&gt;
&lt;p&gt;First of all, there are actually four sound sources: the VCO, the
noise generator, the LFO and the self-resonating filter. But there is
this interesting trade-off between using more sound sources and
constraining the choices you have. For instance, to play the filter you
regulate frequency through the cut-off – but this constrains your
ability to modulate the filter for other purposes. Similarily, if you
use the LFO as a sound source, you have limited ability to use it to
modulate the VCO.&lt;/p&gt;
&lt;p&gt;Secondly, I find that there is a lot of fun to be had on each patch.
For each patch, there are many ways to play it. You can play on the
keyboard, or fire up a simple sequence, or try to generate something.
What I tend to do is to let the sequence contain only beat info, and
improvise melodies on top of the beat. Then I find some cool transitions
and put together piece from that.&lt;/p&gt;
&lt;p&gt;Some fun things I have tried with the patching, thus far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using the noise generator as a snare-drum, controlled by the accent
on the sequencer. I think this came from the manual. I found that
routing the accent through the mult to both cut-off and mix CV gave the
best result.&lt;/li&gt;
&lt;li&gt;Using the random-on-step mode to control the LFO-frequency.
Depending on what is modulated by the LFO this introduces some funky
randomness to the playing.&lt;/li&gt;
&lt;li&gt;Using the LFO as a tempo clock for more variable tempo.&lt;/li&gt;
&lt;li&gt;Switch the VCF modulation polarity and turn up the modulation so
that the filter becomes like an inverted VCA, with attack and decay
switching roles.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="how-modular-is-it"&gt;How modular is it?&lt;/h4&gt;
&lt;p&gt;So, from my perspective of wanting to get into hardware modular
synths, where is the Mother-32? Is it a &lt;em&gt;true modular&lt;/em&gt; or is it
&lt;em&gt;just a synth&lt;/em&gt;? I will say &lt;strong&gt;it is 40–60&lt;/strong&gt;. Fourty
percent of modular and sixty percent of a synth. However, to expand it I
am definitely getting it some modular friends.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/tutorials/youtube.html</id>
    <title>YouTube self-defence</title>
    <updated>2019-03-21T12:00:00Z</updated>
    <published>2019-03-21T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/tutorials/youtube.html"/>
    <content type="html">&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Youtube"&gt;YouTube&lt;/a&gt; is
Google’s&lt;a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; huge video streaming site. It has a
large number of creators who upload their content there&lt;a href="#fn2"
class="footnote-ref" id="fnref2" role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;.
Some video content is good, most of it is bad – and some of it directly
harmful. Google is intent upon steering YouTube viewers&lt;a href="#fn3"
class="footnote-ref" id="fnref3" role="doc-noteref"&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; to
bad and harmful content. &lt;em&gt;Therefore I have composed a list of defence
strategies for YouTube viewers.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="blocking-ads"&gt;Blocking ads&lt;/h2&gt;
&lt;p&gt;The most obvious attack vector on YouTube is ads trying to manipulate
you while you are watching the good content.&lt;/p&gt;
&lt;p&gt;The most reliable way to block ads right now is to use &lt;a
href="https://www.mozilla.org/firefox/new/"&gt;Firefox&lt;/a&gt; with the &lt;a
href="https://addons.mozilla.org/addon/ublock-origin/"&gt;uBlock Origin&lt;/a&gt;
plugin (which is also available for Android and &lt;a
href="https://github.com/gorhill/uBlock/"&gt;other platforms&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id="hiding-suggestions"&gt;Hiding suggestions&lt;/h2&gt;
&lt;p&gt;The next attack vector is located on the right hand side of the
screen:&lt;/p&gt;
&lt;figure&gt;
&lt;img src="/img/youtube-suggestion.png"
alt="YouTube suggestions marked in red." /&gt;
&lt;figcaption aria-hidden="true"&gt;YouTube suggestions marked in
red.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In addition to taking up space which could be used for the video,
this space is often filled with bad video suggestions.&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;First, install &lt;a
href="https://addons.mozilla.org/addon/ublock-origin/"&gt;uBlock
Origin&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The feature of uBlock Origin we are going to use can actually, be
used for blocking parts of any page, and is a useful way to get rid of
clutter on pages you visit often.&lt;/p&gt;
&lt;ol start="2" type="1"&gt;
&lt;li&gt;Right click on the white space close to the suggestions:&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
&lt;img src="/img/youtube-step-1.png"
alt="This is where you should right click." /&gt;
&lt;figcaption aria-hidden="true"&gt;This is where you should right
click.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol start="3" type="1"&gt;
&lt;li&gt;Select the uBlock origin block option&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
&lt;img src="/img/youtube-step-2.png"
alt="The uBlock option in the right-click-menu." /&gt;
&lt;figcaption aria-hidden="true"&gt;The uBlock option in the
right-click-menu.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol start="4" type="1"&gt;
&lt;li&gt;Check that the red area covers the suggestion section.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Currently this page-element is called &lt;code&gt;###secondary&lt;/code&gt;. You
can use the mouse to select the correct region if you right-clicked in
the wrong place.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="/img/youtube-step-3.png"
alt="uBlock shows you which part of the web-site you are blocking." /&gt;
&lt;figcaption aria-hidden="true"&gt;uBlock shows you which part of the
web-site you are blocking.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ol start="5" type="1"&gt;
&lt;li&gt;Click &lt;em&gt;Create&lt;/em&gt; to create the filter, removing the
suggestions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;While you are at it, you could create another filter to block the
comment section YouTube.&lt;/p&gt;
&lt;h2 id="downloading-youtube-videos"&gt;Downloading YouTube videos&lt;/h2&gt;
&lt;p&gt;Sometimes the best way to protect yourself is to avoid the fight
entirely. There are tools available which will allow you to download a
video from YouTube, without visiting the site yourself.&lt;/p&gt;
&lt;p&gt;If you are comfortable in a command line, the &lt;code&gt;youtube-dl&lt;/code&gt;
is straight forward to use:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;youtube-dl &amp;lt;link-to-video&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Actually, &lt;code&gt;youtube-dl&lt;/code&gt; will download videos and music from
a lot of different sites – not just YouTube!&lt;/p&gt;
&lt;h2 id="blocking-auto-play"&gt;Blocking auto-play&lt;/h2&gt;
&lt;p&gt;One of the ways YouTube controls what you watch is by automatically
playing a new video just after the one you were watching finished. As a
user you have no control over what video YouTube choses for you to see
next. There is a button to disable auto-playing, but it is completely
under YouTube’s control. In order to take back control, you can
&lt;strong&gt;disable autoplaying video content&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Firefox allows you to change your autoplay settings by going to the
special page &lt;code&gt;about:config&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In recent versions, the main option is called
&lt;code&gt;media.autoplay.default&lt;/code&gt; and can have one of three values
(See table below).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;To block autoplay completely, set the value to 1.&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: left;"&gt;&lt;code&gt;media.autoplay.default&lt;/code&gt;
value&lt;/th&gt;
&lt;th style="text-align: left;"&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Value: 0&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Autoplay allowed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Value: 1&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Autoplay blocked.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: left;"&gt;Value: 2&lt;/td&gt;
&lt;td style="text-align: left;"&gt;Prompt the user.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are more option related to autoplay, such as
&lt;code&gt;media.autoplay.allow-muted&lt;/code&gt;, and I wish it was easier to
find their documentation from Firefox’s GUI. But usually, a bit of
searching will give a hint.&lt;/p&gt;
&lt;h2 id="surf-in-a-private-window"&gt;Surf in a private window&lt;/h2&gt;
&lt;p&gt;If you are logged-in with a Google Account while watching YouTube,
Google will remember what you have been watching and use this
information for whatever it wants. Google has privacy options, but they
are completely under Google’s control and therefore we cannot trust
them.&lt;/p&gt;
&lt;p&gt;Even if you do not have a Google Account, Youtube contains other
tracking mechanisms which allow them to collect data about your
viewing.&lt;/p&gt;
&lt;p&gt;Therefore, always open YouTube in a private window.&lt;a href="#fn4"
class="footnote-ref" id="fnref4" role="doc-noteref"&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; You
should also be using tracker protecting software such as &lt;a
href="https://www.eff.org/privacybadger"&gt;Privacy Badger&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="channel-rss-feeds"&gt;Channel RSS feeds&lt;/h2&gt;
&lt;p&gt;Feeds (RSS or Atom) are way to get updates on a particular site.
There are a lot of different RSS readers to be found&lt;a href="#fn5"
class="footnote-ref" id="fnref5" role="doc-noteref"&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;,
for instance as Firefox plugins. If you use a feed reader, you can get
updates from the channels you are interested directly in the FeedReader.
The advantage is that you do not need a Google Account to read the
feed.&lt;/p&gt;
&lt;p&gt;Currently, you can get a feed URL for a channel in YouTube, in the
following way:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;Take the address of the channel.
&lt;ul&gt;
&lt;li&gt;Example:
&lt;code&gt;https://www.youtube.com/channel/UCzLl8NF-hiP2HMq5dL2NQOQ&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Copy the code at the end (after &lt;code&gt;channel/&lt;/code&gt;).
&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;UCzLl8NF-hiP2HMq5dL2NQOQ&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Paste it at the end of this address:
&lt;code&gt;https://www.youtube.com/feeds/videos.xml?channel_id=&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Example:
https://www.youtube.com/feeds/videos.xml?channel_id=UCzLl8NF-hiP2HMq5dL2NQOQ&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now you have a feed address which you can give you any RSS
feed-reader, to receive updates when the channel releases new
videos.&lt;/p&gt;
&lt;p&gt;Some feed readers will do this conversion for you automatically if
you give them the channel url.&lt;/p&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document"
role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;Google did not create YouTube, but bought it in 2006,
after it became popular.&lt;a href="#fnref1" class="footnote-back"
role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2"&gt;&lt;p&gt;If you are creating a video which you want to release
upon the public, consider putting it somewhere more friendly to your
viewers.&lt;a href="#fnref2" class="footnote-back"
role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn3"&gt;&lt;p&gt;Your children included!&lt;a href="#fnref3"
class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn4"&gt;&lt;p&gt;I have actually just turned off all history and stored
data in Firefox, except for bookmarks. I aggressively bookmark and tag
pages I visit, so that I still get a useful auto-completion in the
address bar on stuff I have visited before.&lt;a href="#fnref4"
class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn5"&gt;&lt;p&gt;Personally, I use &lt;a
href="https://www.newsboat.org/"&gt;newsboat&lt;/a&gt;, because I can then have
it running in &lt;code&gt;tmux&lt;/code&gt; on my server.&lt;a href="#fnref5"
class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/antipattern/index.html</id>
    <title>The anti-pattern game</title>
    <updated>2019-03-04T12:00:00Z</updated>
    <published>2019-03-04T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/antipattern/index.html"/>
    <content type="html">&lt;p&gt;Here is a small game I though of when taking a course on &lt;a
href="https://en.wikipedia.org/wiki/Modal_logic"&gt;modal logic&lt;/a&gt;. It is
a bit too tedious to be played by humans, but I had great fun finding a
winning stategy for it – and there are still simple questions about this
game I cannot answer.&lt;/p&gt;
&lt;h2 id="the-rules"&gt;The rules&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;The anti-pattern game&lt;/em&gt; is a two-player game. It is played
using black and white pebbles (like Go). These pebbles are placed in
sequence on a line. On their turn the player has a simple choice: to
continue the sequence with a white or a black pebble.&lt;/p&gt;
&lt;p&gt;A player looses if they put down a pebble such that the sequence
contains a &lt;em&gt;pattern&lt;/em&gt;. A &lt;em&gt;pattern&lt;/em&gt; is a sequence of pebbles
repeated three times in a row.&lt;/p&gt;
&lt;p&gt;A player wins if the other player looses.&lt;/p&gt;
&lt;h3 id="example"&gt;Example&lt;/h3&gt;
&lt;p&gt;Here is a simlpe game won by player 1:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ○ ● ● ○ ○ ● ● ○ ○ ●
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Player two lost because after their final turn, the sequence ended
with the pattern: &lt;code&gt;● ○ ○ ●&lt;/code&gt; repeated trice.&lt;/p&gt;
&lt;p&gt;Player two could have chosen to play &lt;code&gt;○&lt;/code&gt; instead on the
final turn, but that would also be a loosing move since then
&lt;code&gt;○&lt;/code&gt; would have been repeated trice. So if player two could
have won, it must have changed its course several moves ago.&lt;/p&gt;
&lt;h2 id="a-winning-strategy-ready-player-1"&gt;A winning strategy
&lt;code&gt;– READY PLAYER 1&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The obvious question about any such two-player game is weather any
player has a &lt;em&gt;winning strategy&lt;/em&gt;. Often this can be determined by
a finiteness condition, but here we could at least imagine that the game
could go on to generate an infinitely long sequence.&lt;/p&gt;
&lt;p&gt;To solve this question I wrote a short Haskell program which does a
brute force search to find a winning strategy. Actually, the Haskell
program wasn’t that short – because I wanted to apply modal logic to
formulate the winning strategy condition and had to make appropriate
definitions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;As it turns out, there is a winning strategy for player
1&lt;/strong&gt;, and they can win the game inn less than twenty-two moves.
The Haskell program finds the solution represented as a finite tree,
which decides the moves of player 1 given any possible move of player
2.&lt;/p&gt;
&lt;h2 id="generalisations"&gt;Generalisations&lt;/h2&gt;
&lt;p&gt;Even though the game is solved, there are more questions we could
pose if we make small adjustments to the game. Some of these questions I
do not yet know the answer to.&lt;/p&gt;
&lt;h3 id="cooperating-players"&gt;Cooperating players&lt;/h3&gt;
&lt;p&gt;This question is simple to formulate: If the palyers were
cooperating, &lt;strong&gt;could the game go on for ever?&lt;/strong&gt; Put more
precisely:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is there an infinite binary sequence where no contigous subsequence
is of the form &lt;code&gt;σσσ&lt;/code&gt; for some sequence &lt;code&gt;σ&lt;/code&gt; of
non-zero length?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First off, it is clear that this game can continue for a long time.
Here is a game with a thousand played moves:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ●
○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ○ ○ ● ● ○ ● ● ○
● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ●
● ○ ● ● ○ ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○
○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ○
● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ●
○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○
● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○
● ● ○ ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ●
● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ○ ● ●
○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ●
○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○
● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ○ ● ● ○ ● ● ○
● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ●
● ○ ● ● ○ ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ●
○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ○
● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ●
○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○
● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○
● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ●
● ○ ● ○ ● ● ○ ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○
● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ●
○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○
● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ○ ● ● ○ ● ● ○ ● ○ ●
● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ●
● ○ ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ●
○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ○ ● ● ○
● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ●
○ ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○
● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ○ ● ● ○ ●
● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ●
○ ● ● ○ ● ● ○ ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ●
○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○
● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ●
● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ○ ● ● ○ ● ● ○
○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ●
● ○ ● ● ○ ○ ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ●
○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○
○ ● ● ○ ● ● ○ ● ○ ● ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ●
● ○ ● ● ○ ○ ● ● ○ ● ● ○ ● ○ ● ● ○ ○ ● ● ○ ● ● ○ ●&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first sight this might seem disorderly, but there is a lot of
repetition here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The sequence of the first three pebbles &lt;code&gt;● ● ○&lt;/code&gt; covers
most of the game:
&lt;ul&gt;
&lt;li&gt;&lt;a
href="../img/anti-pattern-1000-first-3-repetition.png"&gt;Image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The entire first line (25 pebbles) occurs several times (even at the
25 character line offset):
&lt;ul&gt;
&lt;li&gt;&lt;a
href="../img/anti-pattern-1000-line-repetition.png"&gt;Image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The fact that &lt;code&gt;● ● ○&lt;/code&gt; is so prominent in this example,
suggest a way to generate an infinite game sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;data Colour = Black | White
 deriving (Eq, Ord, Show)

instance Show Colour where
  show Black = &amp;quot;●&amp;quot;
  show White = &amp;quot;○&amp;quot;

generate :: [Colour] -&amp;gt; [Colour]
generate p = [Black,Black,White]
  ++ (case p of
       (Black : cs) -&amp;gt; White : generate cs
       (White : cs) -&amp;gt; [Black,White] ++ generate cs )

stream :: [Colour]
stream = generate stream&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes &lt;code&gt;stream&lt;/code&gt; an inductively defined stream of
pebbles, which makes up an &lt;strong&gt;infinitely long game&lt;/strong&gt;. An
interesting question is then: Can player 1 force the game to go on
idefinitely (assuming player 2 will not loose if avoidable)?&lt;/p&gt;
&lt;p&gt;As an aside: This stream, while devoid of direct repetition is
&lt;em&gt;very&lt;/em&gt; &lt;strong&gt;compressible&lt;/strong&gt;. It is also an example of
data which responds well to being compressed several times. Here are the
&lt;a href="stream.txt.gz.gz"&gt;first 1 million moves&lt;/a&gt; of the stream
compressed twice. The file is a mere 512 bytes, and unpacks to a 26kb
file, which again unpacks to 3Mb. That’s a compression factor of almost
6000!&lt;a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="more-colours"&gt;More colours&lt;/h3&gt;
&lt;p&gt;What if the game had more colours? What if there were three colours
of pebbles, not just two?&lt;/p&gt;
&lt;h3 id="more-repetition-allowed"&gt;More repetition allowed&lt;/h3&gt;
&lt;p&gt;The choice that three repetitions form a pattern is arbitrary. What
if we allowed three repetitions, but prohibited four? Clearly the games
would be longer, but would it make an essential difference to wether a
player has a winning strategy?&lt;/p&gt;
&lt;h3 id="more-players"&gt;More players&lt;/h3&gt;
&lt;p&gt;What if there are more players? This could influence the dynamics,
and I do not know of a winning strategy for the three player variant.
Since the game could go on for ever, it is not obvious that there is a
winning strategy for any player when he controls only a third of the
moves.&lt;/p&gt;
&lt;p&gt;There is also a question of who winns in a three player game. Below
is a record of one, where player 1 places the loosing pebble.
&lt;strong&gt;But did player 2 or player 3 win?&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ○ ● ○ ● ● ○ ● ○ ● ○ ○ ● ○ ● ○ ○ ● ○ ● ○ ○
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Different winning conditions would give different incentives. Here
are two possible winning conditions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cooperative victory:&lt;/strong&gt; If a player looses the other
two win.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exclusive victory:&lt;/strong&gt; If player &lt;code&gt;n&lt;/code&gt; looses,
then player &lt;code&gt;n + 1 (mod 3)&lt;/code&gt; wins.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;In the cooperative variant&lt;/em&gt; it is clear that any two players
could cooperate to win – basically because they out-number the third.
But in a neurtal setting, who could cooperate? Player 1’s first move has
no effect, but player 2 could play the same colour as Player 1, in order
to open up for a cooperation with player 1. Then player 3 has a forced
move, and when Player 1 is ready to make his move again, the board looks
as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ?
1 2 3 1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If player 1 plays &lt;code&gt;●&lt;/code&gt; now, he and player 2 can force
player 3 to loose:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ● ● ○ ● ● ○ 
1 2 3 1 2 3 1 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If player 1 instead plays &lt;code&gt;○&lt;/code&gt; the playing field is more
open, and player 3 gets to chose his move:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ○ ● ?
1 2 3 1 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But even though player 2 and player 3 can cooperate to force player
1’s moves in this setup, player 3 would loose the sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ○ ● ● ○ ● ● ○ ● ●
1 2 3 1 2 3 1 2 3 1 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thus, for the cooperative variant, the question is: Can either player
1 or player 2 choose to cooperate with player 3 instead? The answer
remains elusive for the time being.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In the exclusive variant&lt;/em&gt; the player 2 does not want to help
player 1 win, so&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;● ● ○ ● ● ○ ● ● ○ 
1 2 3 1 2 3 1 2 3&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is not acceptable to player 2. However, it now unclear if any player
has a winning strategy, or if given perfect play from each player the
game would go on idefinitely.&lt;/p&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document"
role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;The factor gets better as the stream progresses: the
first 100 million moves can be compressed to a &lt;a
href="nottiny.txt.gz.gz.gz"&gt;small 7.2kb file&lt;/a&gt; — unpacking it
completely you might find that your text editor will struggle while
opening the resulting file.&lt;a href="#fnref1" class="footnote-back"
role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/tutorials/acme-agda.html</id>
    <title>Writing Agda Code in Another Edtior</title>
    <updated>2019-01-02T12:00:00Z</updated>
    <published>2019-01-02T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/tutorials/acme-agda.html"/>
    <content type="html">&lt;p&gt;Officially the only editor supported by the &lt;a
href="http://wiki.portal.chalmers.se/agda/"&gt;Agda&lt;/a&gt;-community is Emacs,
through the Agda Emacs Mode. It is true that one forsakes many features
by using another editor, but I want to convey my experience of using &lt;a
href="http://acme.cat-v.org/"&gt;Acme&lt;/a&gt; for editing Agda code, and say
something in general about editing Agda code without agda-mode.&lt;/p&gt;
&lt;h2 id="writing-agda-without-the-training-wheels"&gt;Writing Agda without
the training wheels?&lt;/h2&gt;
&lt;p&gt;Writing Agda-code can be seen as a very interactive process. You say
where you want to go, give a partial solution containing one or more
holes, and Agda will inform you what goals you have to reach in order to
fill the gaps of your reasoning. The ability to leave holes is one of
Agda’s greatest features, and if you have never tried programming like
this — you should!&lt;/p&gt;
&lt;p&gt;However, I often find the code which comes out of this process is not
always the best. Some times I leave a hole, but the bits I wrote around
the hole are not really helping. As I chase down the hole, I find my
self adding more and more code to make the essence of the proof fit the
oddly shaped hole I made. Of course I might realise my mistake, but if I
first manage to get the hole filled then the motivation to start
refactoring stuff to make it beautiful is low.&lt;/p&gt;
&lt;p&gt;How to avoid this? I am not sure. In the course of solving a
difficult problem one is bound to take detours and one will be lucky to
arrive at an optimal solution at the first attempt. This seems inherent
to the way we humans solve problems. I think that relying a less on the
guidance of agda-mode, one can develop a better understanding of the
matter at hand — that is the type checker, and the reduction of
expressions.&lt;/p&gt;
&lt;h2 id="case-study-agda-in-acme"&gt;Case study: Agda in Acme&lt;/h2&gt;
&lt;p&gt;Acme is a fantastic programming environment — a true pearl from &lt;a
href="https://en.wikipedia.org/wiki/Plan_9"&gt;forgotten times&lt;/a&gt;. Acme
was designed with &lt;a href="unicode.html"&gt;Unicode editing&lt;/a&gt; in mind. It
makes very few assumptions about the nature of what you are editing, but
rather integrates it self to the other tools on the system. So what
happened when I tried to use it to write Agda code?&lt;/p&gt;
&lt;p&gt;First thing one notices is that there is no syntax highlighting for
Agda. Actually Acme has no syntax highlighting what-so-ever! However
strange as it may sound, once you are used to living without, you do not
miss it. In stead of a circus of colours on your screen, you get to
focus on the beauty of the code itself. One effect of this is that I
become less tolerant to clutter in the code, especially in the form of
commented out code.&lt;/p&gt;
&lt;p&gt;Next thing I did was to write &lt;a href="../downloads/Watch"&gt;a small
script&lt;/a&gt; which runs a specific command periodically and monitors the
output in an Acme window. Running the type checker in this way gives
instant feedback on the status of my code every time I save the file —
which I do often. One of the strengths of Acme is that the &lt;a
href="http://doc.cat-v.org/plan_9/4th_edition/papers/plumb"&gt;plumber&lt;/a&gt;
— a complementary program working in sync with Acme — understands the
kind of file-line-column adresses a compiler error comes with. So
without any extra efforts I can right click the errors from
&lt;code&gt;agda&lt;/code&gt; to jump to the right place in the code.&lt;/p&gt;
&lt;p&gt;Even without the interactive mode, making holes is useful, but I
found that I more often would factor out the holes to a lemma with a
type declaration — usually using &lt;code&gt;where&lt;/code&gt; — and just letting
the definition be &lt;code&gt;?&lt;/code&gt;. This would make it clear from just
looking at the code what is missing. It also gave time to stop and think
about the structure of the proof.&lt;/p&gt;
&lt;p&gt;After writing like this for a while, I started having the deprecated
Agda Interactive Mode running in an Acme window. Mostly just to evaluate
expressions in the context of a hole, or check the odd type. I would
also use this space as a scratch pad, writing down the types of various
expressions currently under consideration.&lt;/p&gt;
&lt;p&gt;To replace the jumping to the definition of a term functionality, I
keep the following grep in my tagline:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; rc -c &amp;#39;echo -n &amp;#39;&amp;#39;^&amp;#39;&amp;#39;; cat ; echo &amp;#39;&amp;#39; &amp;#39;&amp;#39;&amp;#39; | grep -rn -f - $AGDA_STD&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Certainly there is room for improvement on this one. I only spent one
minute on the problem. However, even this simple solution allows me to
mark a term with the mouse then middle-click the tag to get the type
declaratation and definition of the term pop up in a window. This also
prints the file and line number of the definition, so I can right click
on that to open the file. Additional directories, such as the current
project are simply added to the end of this command, and it will search
those as well.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;AGDA_STD&lt;/code&gt; variable you see above is just an
environment variable with the path to the agda standard library. To
compile Agda-code I just use an mkfile with the following pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;%.agdai: %.agda
    agda -i . -i $AGDA_STD $stem.agda&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="conclusions-and-the-future"&gt;Conclusions and the future&lt;/h2&gt;
&lt;p&gt;What I hope this shows is that Agda only works in Emacs is a truth
with modificaions. Certainly some features of Agda are only available
through the emacs mode, but these features are not essential to writing
Agda code. Indeed showing some restriction as to which features one uses
may improve overall code quality and readability.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/tutorials/latex-maths-unicode.html</id>
    <title>Unicode for mathematics symbols in LaTeX</title>
    <updated>2019-01-02T12:00:00Z</updated>
    <published>2019-01-02T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/tutorials/latex-maths-unicode.html"/>
    <content type="html">&lt;p&gt;&lt;a href="unicode.html"&gt;We know&lt;/a&gt; how to input all the fancy Unicode
mathematics symbols, but a simple text file in markdown still does not
have nearly the sophistication of a Latex document — and for the most
part that is a good thing. When complexity is not needed, it is nice to
keep it at a safe distance. Sometimes, however, you really need to
typeset some complicated equation; with sums indexing over uncountable
sets and beautiful fractions whose denominator tend to zero. Or maybe
you have a killer, commutative diagram which you have to typeset in
xypic?&lt;/p&gt;
&lt;p&gt;In any case you might happen to be typing and by new habit you happen
to type the unicode character ℝ in stead of &lt;code&gt;\mathbb{R}&lt;/code&gt;.
What happens next is that your latex compiler starts yelling at you.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;! Package inputenc Error: Unicode char \u8:ℝ not set up for use with LaTeX.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why is this? You dutyfully had
&lt;code&gt;\usepackage[utf8]{inputenc}&lt;/code&gt;. Is that not enough? Clearly,
not.&lt;/p&gt;
&lt;p&gt;Turns out, this is a call for action. If you want to use fancy UTF-8
symbols in Latex, you must configure how they are interpreted. This is a
good thing, because you can let your own personal preferences decide how
it should work.&lt;/p&gt;
&lt;p&gt;&lt;a
href="https://en.wikibooks.org/wiki/LaTeX/Special_Characters#Extending_the_support"&gt;WikiBooks&lt;/a&gt;
helpfully explains how this is done. All you need to do is to declare
each symbol you want to use at the top of your document. The declations
look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\DeclareUnicodeCharacter{211D}{\ensuremath{\mathbb{R}}}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;211D&lt;/code&gt; is the Unicode code point of ℝ.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Notice&lt;/em&gt; that we use &lt;code&gt;\ensuremath{}&lt;/code&gt; in order to
make sure that the symbol is used in math mode. This allows us to type a
naked ℝ in the middle of the text without surrounding it with dollar
signs.&lt;/p&gt;
&lt;p&gt;What? Is your preamble already too crowded to find your
&lt;code&gt;\author&lt;/code&gt; declaration? Then better put all the symbol
declarations in a &lt;code&gt;.sty&lt;/code&gt; file and include it as a
package.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\usepackage{utf8-symbols}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To make life easier for myself, I wrote this little &lt;a
href="/downloads/utf8-latex-gen.rc"&gt;ten-line rc-script&lt;/a&gt; to add new
entries in such a sty-file. Just run it, type your symbol and the
associated Latex command, and it will generate an entry as described in
the wikibook. The script uses the &lt;a href="XCompose"&gt;XCompose&lt;/a&gt; file
from &lt;a href="unicode.html"&gt;this article&lt;/a&gt; to look up the code of the
symbol you typed, so make sure to have it before running the script.&lt;/p&gt;
&lt;p&gt;You can download my current &lt;a
href="/downloads/utf8-symbols.sty"&gt;utf8-symbols.sty&lt;/a&gt; if you want a
starting point for your own.&lt;/p&gt;
&lt;p&gt;Here is an example latex file which uses it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;\documentclass[a4paper,12pt]{article}

\usepackage[utf8]{inputenc}
\usepackage{utf8-symbols}

\usepackage{amsmath}
\usepackage{amssymb}

\title{Lorem ip-∑}

\begin{document}
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor, π, incididunt ut labore $2^n = ∑_{0 ≤ i &amp;lt; n} 2^i + 1 $ et dolore
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur $0 = 1 + e^{π i}$. Excepteur sint occaecat 
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim
id est laborum.

\begin{align}
 &amp;amp;f : ℝ → ℝ² \\
 &amp;amp;f(x) ≔ (x² , \lim_{a → x⁺} e^{-\frac 1 a})
\end{align}

\end{document}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reading it still takes a bit of Latex knowledge. However, it makes it
a bit easier to skim a formula.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Exercise:&lt;/em&gt; Write a script that reads the assignments in
utf8-symbols.sty and automatically replaces the latex commands with the
corresponding Unicode symbols. This is useful for updating old
files.&lt;/p&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/tutorials/unicode.html</id>
    <title>Every-day Unicode</title>
    <updated>2019-01-01T12:00:00Z</updated>
    <published>2019-01-01T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/tutorials/unicode.html"/>
    <content type="html">&lt;p&gt;This document is a short guide to writing unicode on systems with
Xorg X11, such as Linux or *BSD.&lt;/p&gt;
&lt;p&gt;Unicode is a systematisation of symbols, and contains just about any
symbol you can imagine. The most common encoding of Unicode on computers
is called UTF8, which overlaps with ASCII on the first 7 bits.&lt;/p&gt;
&lt;h2 id="xcompose"&gt;XCompose&lt;/h2&gt;
&lt;p&gt;Xorg has allow configuration of a compose key for mapping sequences
of keystrokes to characters. For example, on my current setup i can type
the greek letter π (pi), using the keystroke sequnce
&lt;code&gt;&amp;lt;RWIN&amp;gt; * p&lt;/code&gt;. That is first pressing once on the
menu-button, then typing *, followed by p. Notice that these keys are
pressend in sequence, not simultaneously.&lt;/p&gt;
&lt;h3 id="the-xcompose-file"&gt;The XCompose file&lt;/h3&gt;
&lt;p&gt;You can replace the default sequence mapping with a costom one, by
writing it to the file &lt;code&gt;~/.XCompose&lt;/code&gt;. I use an &lt;a
href="XCompose"&gt;XCompose file&lt;/a&gt; which derives from the &lt;a
href="http://en.wikipedia.org/wiki/Plan_9"&gt;Plan 9&lt;/a&gt; keyboard file. It
contains the complete cyrillic and greek alphabets, along with a lot of
mathematical notation and useful everyday symbols. The following command
gets the file, and you can inspect it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -o ~/.XCompose https://hakon.gylterud.net/tutorials/XCompose&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The lines of the XCompose file, each one giving a way to input a
symbol, looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;minus&amp;gt; &amp;lt;greater&amp;gt; : &amp;quot;→&amp;quot; U2192&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;minus&amp;gt; &amp;lt;greater&amp;gt;&lt;/code&gt; part
tells you which sequence of keys to enter to produce the symbol. The
sign in question is “→”, which happens to be unicode character with code
U2192.&lt;/p&gt;
&lt;h2 id="setting-the-compose-key"&gt;Setting the compose key&lt;/h2&gt;
&lt;p&gt;To specify which key shall be the compose key, one can use the
command &lt;code&gt;setxkbmap&lt;/code&gt;. For example the following command makes
the «menu»-key the compose key.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;setxkbmap -option &amp;quot;compose:menu&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I have this command in my .xinitrc so that it is run every time I
start XOrg.&lt;/p&gt;
&lt;p&gt;Another good choice may be right «windows»-button,
&lt;code&gt;rwin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; If you want the right shift button to be your
multikey, you need to use xmodmap to remap it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;xmodmap -e &amp;quot;keysym Shift_R = Multi_key&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="gtk-and-qt-applications"&gt;GTK and QT applications&lt;/h3&gt;
&lt;p&gt;The following environment variable assignments hint GTK and QT
applications to use the same compose settings as the rest of Xorg. Put
them somewhere they will be exported to the relevant programs — I have
mine in .xinitrc.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export GTK_IM_MODULE=xim
export QT_IM_MODULE=xim &lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="what-unicode-characters-are-useful"&gt;What unicode characters are
useful?&lt;/h2&gt;
&lt;h3 id="accents"&gt;Accents&lt;/h3&gt;
&lt;p&gt;Accents are often used in names, and being able to correctly write
some ones name shows respect and care for that person.&lt;/p&gt;
&lt;p&gt;Here is an small selection from the XCompose file, to give you an
idea of how the various accents are constructed.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;apostrophe&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;é&amp;quot; U00E9
&amp;lt;Multi_key&amp;gt; &amp;lt;a&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;æ&amp;quot; U00E6
&amp;lt;Multi_key&amp;gt; &amp;lt;o&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;å&amp;quot; U00E5
&amp;lt;Multi_key&amp;gt; &amp;lt;slash&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;ø&amp;quot; U00F8
&amp;lt;Multi_key&amp;gt; &amp;lt;quotedbl&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;ä&amp;quot; U00E4
&amp;lt;Multi_key&amp;gt; &amp;lt;v&amp;gt; &amp;lt;g&amp;gt; : &amp;quot;ǧ&amp;quot; U01E7
&amp;lt;Multi_key&amp;gt; &amp;lt;asciicircum&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;ê&amp;quot; U00EA
&amp;lt;Multi_key&amp;gt; &amp;lt;underscore&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;ō&amp;quot; U014D
&amp;lt;Multi_key&amp;gt; &amp;lt;comma&amp;gt; &amp;lt;c&amp;gt; : &amp;quot;ç&amp;quot; U00E7&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="smileys"&gt;Smileys&lt;/h3&gt;
&lt;p&gt;Textual communication can be difficult to master, and perhaps the
most difficult things to convey are humour and sarcasm. If you want to
make sure the reader understands that you are not completely serious you
can include a smiley.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;colon&amp;gt; &amp;lt;parenleft&amp;gt; : &amp;quot;☹&amp;quot; U2639
&amp;lt;Multi_key&amp;gt; &amp;lt;colon&amp;gt; &amp;lt;parenright&amp;gt; : &amp;quot;☺&amp;quot; U263A&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="the-em-dash-the-en-dash"&gt;The «em» dash &amp;amp; the «en» dash&lt;/h3&gt;
&lt;p&gt;Correct usage of dashes can be confusing, but a first step to
mastering this art is to recognise that there are &lt;a
href="https://en.wikipedia.org/wiki/Dash"&gt;more than one&lt;/a&gt;. The key
which is usually presented on the key board is not a dash, but rather &lt;a
href="https://en.wikipedia.org/wiki/Hyphen"&gt;a hyphen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My personal favorite dash is the em dash, which is one «em» wide —
that is the width of the m character. In my native Norwegian it is
called “tankestrek” (literally “thinking dash”), and is used to set off
parenthetical statements. It is also used when writing quotes such
as:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The ideally non-violent state will be an ordered anarchy. That State
is the best governed which is governed the least. —Mahatma Gandhi&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Another dash is the «en»-dash, the width of an n, it is used They are
both easily input using the below XCompose entries.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;e&amp;gt; &amp;lt;m&amp;gt; : &amp;quot;—&amp;quot; U2014
&amp;lt;Multi_key&amp;gt; &amp;lt;e&amp;gt; &amp;lt;n&amp;gt; : &amp;quot;–&amp;quot; U2013&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Read more about dashes at &lt;a
href="http://practicaltypography.com/hyphens-and-dashes.html"&gt;Butterick’s
Practical Typography&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="the-ellipsis"&gt;The ellipsis&lt;/h3&gt;
&lt;p&gt;A popular symbol often written on computers using three separate
punctation marks, the ellipsis “…” is present in Unicode.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;3&amp;gt; &amp;lt;period&amp;gt; : &amp;quot;…&amp;quot; U2026&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="mathematical-symbols"&gt;Mathematical symbols&lt;/h3&gt;
&lt;p&gt;I love mathematics, but even if you don’t you might need a couple of
mathematical symbools from time to time. The XCompose file mentioned
ealier comtains really a lot of mathematical notation, and it is worth
scrolling through the relevant sections of it. Below is a tiny
selection.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;d&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;°&amp;quot; U00B0
&amp;lt;Multi_key&amp;gt; &amp;lt;i&amp;gt; &amp;lt;s&amp;gt; : &amp;quot;∫&amp;quot; U222B
&amp;lt;Multi_key&amp;gt; &amp;lt;m&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;∈&amp;quot; U2208
&amp;lt;Multi_key&amp;gt; &amp;lt;m&amp;gt; &amp;lt;u&amp;gt; : &amp;quot;×&amp;quot; U00D7
&amp;lt;Multi_key&amp;gt; &amp;lt;s&amp;gt; &amp;lt;r&amp;gt; : &amp;quot;√&amp;quot; U221A
&amp;lt;Multi_key&amp;gt; &amp;lt;minus&amp;gt; &amp;lt;colon&amp;gt; : &amp;quot;÷&amp;quot; U00F7
&amp;lt;Multi_key&amp;gt; &amp;lt;period&amp;gt; &amp;lt;period&amp;gt; : &amp;quot;·&amp;quot; U00B7
&amp;lt;Multi_key&amp;gt; &amp;lt;f&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;∀&amp;quot; U2200
&amp;lt;Multi_key&amp;gt; &amp;lt;t&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;∃&amp;quot; U2203
&amp;lt;Multi_key&amp;gt; &amp;lt;t&amp;gt; &amp;lt;f&amp;gt; : &amp;quot;∴&amp;quot; U2234
&amp;lt;Multi_key&amp;gt; &amp;lt;t&amp;gt; &amp;lt;u&amp;gt; : &amp;quot;⊢&amp;quot; U22A2
&amp;lt;Multi_key&amp;gt; &amp;lt;asciitilde&amp;gt; &amp;lt;minus&amp;gt; : &amp;quot;≃&amp;quot; U2243
&amp;lt;Multi_key&amp;gt; &amp;lt;asciitilde&amp;gt; &amp;lt;equal&amp;gt; : &amp;quot;≅&amp;quot; U2245
&amp;lt;Multi_key&amp;gt; &amp;lt;N&amp;gt; &amp;lt;N&amp;gt; : &amp;quot;ℕ&amp;quot; U2115
&amp;lt;Multi_key&amp;gt; &amp;lt;O&amp;gt; &amp;lt;plus&amp;gt; : &amp;quot;⊕&amp;quot; U2295
&amp;lt;Multi_key&amp;gt; &amp;lt;P&amp;gt; &amp;lt;P&amp;gt; : &amp;quot;ℙ&amp;quot; U2119
&amp;lt;Multi_key&amp;gt; &amp;lt;Q&amp;gt; &amp;lt;Q&amp;gt; : &amp;quot;ℚ&amp;quot; U211A
&amp;lt;Multi_key&amp;gt; &amp;lt;R&amp;gt; &amp;lt;R&amp;gt; : &amp;quot;ℝ&amp;quot; U211D
&amp;lt;Multi_key&amp;gt; &amp;lt;s&amp;gt; &amp;lt;0&amp;gt; : &amp;quot;⁰&amp;quot; U2070
&amp;lt;Multi_key&amp;gt; &amp;lt;s&amp;gt; &amp;lt;1&amp;gt; : &amp;quot;¹&amp;quot; U00B9
&amp;lt;Multi_key&amp;gt; &amp;lt;s&amp;gt; &amp;lt;2&amp;gt; : &amp;quot;²&amp;quot; U00B2
&amp;lt;Multi_key&amp;gt; &amp;lt;s&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;º&amp;quot; U00BA&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="greek-letters"&gt;Greek letters&lt;/h3&gt;
&lt;p&gt;The Greek alphabet is used frequently in science and mathematics, and
is also useful for writing Greek. Below are the XCompose entries for the
lower case Greek alphavet. They all start with *, so they are quite easy
to guess.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;α&amp;quot; U03B1
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;b&amp;gt; : &amp;quot;β&amp;quot; U03B2
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;c&amp;gt; : &amp;quot;ξ&amp;quot; U03BE
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;d&amp;gt; : &amp;quot;δ&amp;quot; U03B4
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;ε&amp;quot; U03B5
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;f&amp;gt; : &amp;quot;φ&amp;quot; U03C6
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;g&amp;gt; : &amp;quot;γ&amp;quot; U03B3
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;θ&amp;quot; U03B8
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;i&amp;gt; : &amp;quot;ι&amp;quot; U03B9
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;k&amp;gt; : &amp;quot;κ&amp;quot; U03BA
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;l&amp;gt; : &amp;quot;λ&amp;quot; U03BB
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;m&amp;gt; : &amp;quot;μ&amp;quot; U03BC
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;n&amp;gt; : &amp;quot;ν&amp;quot; U03BD
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;ο&amp;quot; U03BF
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;p&amp;gt; : &amp;quot;π&amp;quot; U03C0
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;q&amp;gt; : &amp;quot;ψ&amp;quot; U03C8
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;r&amp;gt; : &amp;quot;ρ&amp;quot; U03C1
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;s&amp;gt; : &amp;quot;σ&amp;quot; U03C3
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;t&amp;gt; : &amp;quot;τ&amp;quot; U03C4
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;u&amp;gt; : &amp;quot;υ&amp;quot; U03C5
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;w&amp;gt; : &amp;quot;ω&amp;quot; U03C9
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;x&amp;gt; : &amp;quot;χ&amp;quot; U03C7
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;y&amp;gt; : &amp;quot;η&amp;quot; U03B7
&amp;lt;Multi_key&amp;gt; &amp;lt;asterisk&amp;gt; &amp;lt;z&amp;gt; : &amp;quot;ζ&amp;quot; U03B6&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="cyrillic-letters"&gt;Cyrillic letters&lt;/h3&gt;
&lt;p&gt;The Cyrillic letters are written starting with @.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;apostrophe&amp;gt; &amp;lt;apostrophe&amp;gt; : &amp;quot;ъ&amp;quot; U044A
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;apostrophe&amp;gt; : &amp;quot;ь&amp;quot; U044C
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;E&amp;gt; : &amp;quot;Е&amp;quot; U0415
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;K&amp;gt; : &amp;quot;К&amp;quot; U041A
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;S&amp;gt; : &amp;quot;С&amp;quot; U0421
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;T&amp;gt; : &amp;quot;Т&amp;quot; U0422
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; : &amp;quot;Ы&amp;quot; U042B
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Z&amp;gt; : &amp;quot;З&amp;quot; U0417
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;е&amp;quot; U0435
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;k&amp;gt; : &amp;quot;к&amp;quot; U043A
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;s&amp;gt; : &amp;quot;с&amp;quot; U0441
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;t&amp;gt; : &amp;quot;т&amp;quot; U0442
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;y&amp;gt; : &amp;quot;ы&amp;quot; U044B
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;at&amp;gt; &amp;lt;z&amp;gt; : &amp;quot;з&amp;quot; U0437
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;C&amp;gt; &amp;lt;H&amp;gt; : &amp;quot;Ч&amp;quot; U0427
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;C&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;Ч&amp;quot; U0427
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;E&amp;gt; &amp;lt;H&amp;gt; : &amp;quot;Э&amp;quot; U042D
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;E&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;Э&amp;quot; U042D
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;K&amp;gt; &amp;lt;H&amp;gt; : &amp;quot;Х&amp;quot; U0425
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;K&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;Х&amp;quot; U0425
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;S&amp;gt; &amp;lt;C&amp;gt; : &amp;quot;Щ&amp;quot; U0429
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;S&amp;gt; &amp;lt;H&amp;gt; : &amp;quot;Ш&amp;quot; U0428
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;S&amp;gt; &amp;lt;c&amp;gt; : &amp;quot;Щ&amp;quot; U0429
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;S&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;Ш&amp;quot; U0428
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;T&amp;gt; &amp;lt;S&amp;gt; : &amp;quot;Ц&amp;quot; U0426
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;T&amp;gt; &amp;lt;s&amp;gt; : &amp;quot;Ц&amp;quot; U0426
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;A&amp;gt; : &amp;quot;Я&amp;quot; U042F
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;E&amp;gt; : &amp;quot;Е&amp;quot; U0415
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;O&amp;gt; : &amp;quot;Ё&amp;quot; U0401
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;U&amp;gt; : &amp;quot;Ю&amp;quot; U042E
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;Я&amp;quot; U042F
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;Е&amp;quot; U0415
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;Ё&amp;quot; U0401
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Y&amp;gt; &amp;lt;u&amp;gt; : &amp;quot;Ю&amp;quot; U042E
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Z&amp;gt; &amp;lt;H&amp;gt; : &amp;quot;Ж&amp;quot; U0416
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;Z&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;Ж&amp;quot; U0416
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;c&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;ч&amp;quot; U0447
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;e&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;э&amp;quot; U044D
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;k&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;х&amp;quot; U0445
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;s&amp;gt; &amp;lt;c&amp;gt; : &amp;quot;щ&amp;quot; U0449
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;s&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;ш&amp;quot; U0448
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;t&amp;gt; &amp;lt;s&amp;gt; : &amp;quot;ц&amp;quot; U0446
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;y&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;я&amp;quot; U044F
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;y&amp;gt; &amp;lt;e&amp;gt; : &amp;quot;е&amp;quot; U0435
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;y&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;ё&amp;quot; U0451
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;y&amp;gt; &amp;lt;u&amp;gt; : &amp;quot;ю&amp;quot; U044E
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;z&amp;gt; &amp;lt;h&amp;gt; : &amp;quot;ж&amp;quot; U0436
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;A&amp;gt; : &amp;quot;А&amp;quot; U0410
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;B&amp;gt; : &amp;quot;Б&amp;quot; U0411
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;D&amp;gt; : &amp;quot;Д&amp;quot; U0414
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;F&amp;gt; : &amp;quot;Ф&amp;quot; U0424
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;G&amp;gt; : &amp;quot;Г&amp;quot; U0413
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;I&amp;gt; : &amp;quot;И&amp;quot; U0418
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;J&amp;gt; : &amp;quot;Й&amp;quot; U0419
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;L&amp;gt; : &amp;quot;Л&amp;quot; U041B
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;M&amp;gt; : &amp;quot;М&amp;quot; U041C
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;N&amp;gt; : &amp;quot;Н&amp;quot; U041D
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;O&amp;gt; : &amp;quot;О&amp;quot; U041E
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;P&amp;gt; : &amp;quot;П&amp;quot; U041F
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;R&amp;gt; : &amp;quot;Р&amp;quot; U0420
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;U&amp;gt; : &amp;quot;У&amp;quot; U0423
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;V&amp;gt; : &amp;quot;В&amp;quot; U0412
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;X&amp;gt; : &amp;quot;Х&amp;quot; U0425
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;a&amp;gt; : &amp;quot;а&amp;quot; U0430
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;b&amp;gt; : &amp;quot;б&amp;quot; U0431
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;d&amp;gt; : &amp;quot;д&amp;quot; U0434
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;f&amp;gt; : &amp;quot;ф&amp;quot; U0444
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;g&amp;gt; : &amp;quot;г&amp;quot; U0433
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;i&amp;gt; : &amp;quot;и&amp;quot; U0438
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;j&amp;gt; : &amp;quot;й&amp;quot; U0439
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;l&amp;gt; : &amp;quot;л&amp;quot; U043B
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;m&amp;gt; : &amp;quot;м&amp;quot; U043C
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;n&amp;gt; : &amp;quot;н&amp;quot; U043D
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;o&amp;gt; : &amp;quot;о&amp;quot; U043E
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;p&amp;gt; : &amp;quot;п&amp;quot; U043F
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;r&amp;gt; : &amp;quot;р&amp;quot; U0440
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;u&amp;gt; : &amp;quot;у&amp;quot; U0443
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;v&amp;gt; : &amp;quot;в&amp;quot; U0432
&amp;lt;Multi_key&amp;gt; &amp;lt;at&amp;gt; &amp;lt;x&amp;gt; : &amp;quot;х&amp;quot; U0445&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/tutorials/darcs.html</id>
    <title>A beginner’s guide to Darcs</title>
    <updated>2018-10-01T12:00:00Z</updated>
    <published>2018-10-01T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/tutorials/darcs.html"/>
    <content type="html">&lt;p&gt;This document is intended as a quick guide to using darcs. It also
also gives some example usage patterns.&lt;/p&gt;
&lt;p&gt;This tutorial is available as&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a
href="http://ichor.openbastille.org/tutorials/darcs.pdf"&gt;PDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href="http://ichor.openbastille.org/tutorials/darcs.html"&gt;HTML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-darcs"&gt;What is darcs?&lt;/h2&gt;
&lt;p&gt;darcs is a version control system, based on patches. A patch
represents some change in the files, and the total collection of changes
constitutes the repository.&lt;/p&gt;
&lt;p&gt;When working on the files, one has a local copy of the repository.
One can work on the files in the local copy as one normally would. After
doing some changes, one records them to make a patch. After the patches
are made they can shared with others, who can incorporate the changes
into their repositories.&lt;/p&gt;
&lt;h2 id="why-use-darcs"&gt;Why use darcs?&lt;/h2&gt;
&lt;p&gt;The motivation for using darcs is that it makes it easier for more
than one person to work on a set of files simultaneously. One does not
need to manually stitch together the changes made. It also gives a
backup of everything, and records the history of the development.&lt;/p&gt;
&lt;p&gt;Darcs works best with text files, such as source code, markup (such
as HTML, or markdown), or plain text files.&lt;/p&gt;
&lt;h2 id="common-commands"&gt;Common commands&lt;/h2&gt;
&lt;p&gt;The following are the basic commands needed in order to use
darcs.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs init&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a new, empty repository in the current directory.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs get&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Creates a copy of a repository. This is only done once to set up the
local copy on your machine.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs add [FILE]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tell darcs to add the [FILE] to the repository.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs record&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a patch from the changes made to the local copy. This is done
every time you have done some change which could be considered a logical
unit.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs pull&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Get patches from another repository.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs push&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Push your patches to another repository.&lt;/p&gt;
&lt;h3 id="example-of-using-darcs"&gt;Example of using darcs&lt;/h3&gt;
&lt;p&gt;Say I would like to work on my Agda computation library. The task at
hand is to add a todo file with my current goals. At the moment there is
no todo list, so when the file is created we need to alert darcs
attension to it by use of &lt;code&gt;darcs add&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="programlisting"&gt;&lt;code&gt;$ darcs get ichor@hub.darcs.net:computation
Copying patches, to get lazy repository hit ctrl-C...
Finished getting.
$ cd computation
$ ls
Computation.agda	Predicate.agda		_darcs/				old/
mkfile
$ cat todo
# TODO
 - Fill out list of things todo
[EOF]
$ darcs add todo
$ darcs record
addfile ./todo
Shall I record this change? (1/2)  [ynW...], or ? for more options: y
hunk ./todo 1
+# TODO
+ - Fill out list of things todo
Shall I record this change? (2/2)  [ynW...], or ? for more options: y
What is the patch name? Added todo file.
Do you want to add a long comment? [yn]n
Finished recording patch &amp;#39;Added todo file.&amp;#39;
$ darcs push
Pushing to &amp;quot;ichor@hub.darcs.net:computation&amp;quot;...
Thu May  7 08:39:34 CEST 2015  Ichor &amp;lt;ichor@Xishan&amp;gt;
  * Added todo file.
Shall I push this patch? (1/1)  [ynW...], or ? for more options: y
Finished applying.
Push successful.&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="more-about-the-basic-commands"&gt;More about the basic
commands&lt;/h3&gt;
&lt;p&gt;To find out more about how each of these commands work, run&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;darcs help [COMMAND]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or read the relevant sections of &lt;a
href="http://www.darcs.net/manual/bigpage.html"&gt;the manual&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="using-darcs"&gt;Using darcs&lt;/h2&gt;
&lt;p&gt;We will now review typical uses of darcs.&lt;/p&gt;
&lt;h3 id="file-manipulation"&gt;File manipulation&lt;/h3&gt;
&lt;p&gt;Files managed by darcs can be edited in any editor. Darcs will
automatically detect changes in the files which are under its
supervision when you do darcs record. Some file manipulations can be
done by darcs, which means that it can gracefully apply these changes in
different contexts. For example moving a file can be done by darcs so
that if another patch changes the same file, before it was moved, the
changes will be applied to the file where it was moved.&lt;/p&gt;
&lt;p&gt;Another useful file operation is replacing a string with another.
This can for example be used to change the name of a function across an
entire project, so that even parallel developments using the old name
will be gracefully changed to the new name when the patch is
applied.&lt;/p&gt;
&lt;p&gt;A good practise is to use &lt;code&gt;replace&lt;/code&gt; to change the
occurences of a file name in other files when moving the file.&lt;/p&gt;
&lt;h4 id="file-manipulation-commands"&gt;File manipulation commands&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;darcs move [FILE] [DEST]`&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Move file to destination&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs replace [OLD] [NEW] [FILE]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace the [OLD] with [NEW] in [FILE]&lt;/p&gt;
&lt;h3 id="patch-dependencies"&gt;Patch dependencies&lt;/h3&gt;
&lt;p&gt;When creating a patch darcs determins which other patches needed to
be in place for the changes to make sense. These patches are the
implicit dependencies of a patch. There are also explicit dependencies,
which you can specify using the flag &lt;code&gt;--ask-deps&lt;/code&gt; when
running &lt;code&gt;darcs record&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When pulling or pushing a patch, darcs will pull/push all its
dependencies.&lt;/p&gt;
&lt;h4 id="example-using-explicit-dependencies."&gt;Example: Using explicit
dependencies.&lt;/h4&gt;
&lt;h3 id="tags"&gt;Tags&lt;/h3&gt;
&lt;p&gt;A tag is a special kind of patch which names the current state of the
repository. The way it does so is by depending on all previous patches.
Since a tag has a lot of dependencies it allows darcs to optimise the
merging of two repositories when they have shared tags.&lt;/p&gt;
&lt;p&gt;Good practise is therefore to tag the state of the repository quite
often. Giving the tag an informative description helps referring to it
later.&lt;/p&gt;
&lt;h4 id="tag-commands"&gt;Tag commands&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;darcs tag&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a tag.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs list tags&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;List the tags in the current repository&lt;/p&gt;
&lt;h3 id="branches"&gt;Branches&lt;/h3&gt;
&lt;p&gt;Repositories which share some patches (but not all) are called
branches. It is often practical to have several branches for each
project — each with a different purpose.&lt;/p&gt;
&lt;h4 id="examples-of-branches"&gt;Examples of branches&lt;/h4&gt;
&lt;p&gt;Some different use cases for branches:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The trunk. A centrally located repository, representing the current
state of development. In coding projects it is good practise to keep the
code in the trunk compiling at all times.&lt;/li&gt;
&lt;li&gt;Working copy. A copy where one is performing current work.&lt;/li&gt;
&lt;li&gt;Feature branch. A branch dedicated to devoping a specific feature.
Once the feature is done and tested, it is pushed to other branches and
can be deleted.&lt;/li&gt;
&lt;li&gt;Version branch. A branch dedicated to a specific version of the
files, for example targetting a public release.&lt;/li&gt;
&lt;li&gt;Fork. A branch of a project intended to be an independent
development.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are all fairly long-lived branches. It is also useful to create
one-off branches for various tasks.&lt;/p&gt;
&lt;h3 id="going-back-in-time"&gt;Going back in time&lt;/h3&gt;
&lt;p&gt;Darcs allow you to create branches which contain any subset of
patches, as long as they are closed under dependencies. This means that
you can go back to an earlier state of the repository. For example when
programming, this allows new work patterns and there are obvious
benefits when trying to locate the source of a regression.&lt;/p&gt;
&lt;p&gt;You can also roll back previous patches by constructing an inverse
patch. An inverse of a patch is a patch which has the effect of undoing
the changes made by the patch. This is useful of if you have revised
some parts of your files, and later find out that the old version was
better. The newer version is still kept in the history of the
repository, so you can continuing your experimentation later, by rolling
back the rolling back.&lt;/p&gt;
&lt;p&gt;Finally, you can obliterate a patch. Obliterating a patch completely
removes it from the current repository. It is recommended to exercise
caution when obliterating patches, as you can loose important work.
Obliterating can for the most part be avoided by using other
techniques.&lt;/p&gt;
&lt;h4 id="commands-for-time-traveling"&gt;Commands for time traveling&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;darcs get --tag [TAG] [REPOSITORY]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This branches [REPOSITORY] and fetches the patches up to [TAG].&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs pull [REPOSITORY]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When pulling [REPOSITORY], darcs will ask you which patches you want
to pull, allowing you to choose the subset you are after.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;darcs rollback&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lets you specified a set of patches, and constructs an inverse patch
for them.&lt;/p&gt;
&lt;h4 id="example-of-cloning-a-repository-up-to-a-tag."&gt;Example of cloning
a repository up to a tag.&lt;/h4&gt;
&lt;p&gt;We can get version 1.0.0 of darcs.&lt;/p&gt;
&lt;pre class="programlisting"&gt;&lt;code&gt; $ darcs get --lazy --tag 1.0.0 darcs.net
   (…)&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="example-of-pulling-only-the-desired-patches"&gt;Example of pulling
only the desired patches&lt;/h4&gt;
&lt;p&gt;Say I would like to get a copy of my Agda computation project and
check that it will compile without the old files.&lt;/p&gt;
&lt;pre class="programlisting"&gt;&lt;code&gt; $ mkdir computation.no-old
 $ cd computation.no-old/
 $ darcs init
 $ darcs pull ichor@hub.darcs.net:ichor/computation
Tue Apr 28 09:26:29 CEST 2015  Ichor &amp;lt;ichor@Xishan&amp;gt;
  * Added computation module.
Shall I pull this patch? (1/4)  [ynW...], or ? for more options: y
Tue Apr 28 09:27:19 CEST 2015  Ichor &amp;lt;ichor@Xishan&amp;gt;
  * Added old computation things.
Shall I pull this patch? (2/4)  [ynW...], or ? for more options: n
Tue Apr 28 09:28:05 CEST 2015  Ichor &amp;lt;ichor@Xishan&amp;gt;
  * Added minimal mkfile
Shall I pull this patch? (3/4)  [ynW...], or ? for more options: y
Thu May  7 08:39:34 CEST 2015  Ichor &amp;lt;ichor@Xishan&amp;gt;
  * Added predicate logic lib.
Shall I pull this patch? (4/4)  [ynW...], or ? for more options: y
Finished pulling and applying.
 $ ls
Computation.agda  _darcs  mkfile  Predicate.agda
 $ mk all
(…)
Finished Computation.&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="example-of-rolling-back-a-patch"&gt;Example of rolling back a
patch&lt;/h4&gt;
&lt;h4 id="example-of-locating-a-regression"&gt;Example of locating a
regression&lt;/h4&gt;
&lt;h3 id="amending"&gt;Amending&lt;/h3&gt;
&lt;h3 id="conflicts"&gt;Conflicts&lt;/h3&gt;
&lt;h3 id="testing"&gt;Testing&lt;/h3&gt;
&lt;h3 id="signing"&gt;Signing&lt;/h3&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/opinion/logic-and-creativity.html</id>
    <title>Logic and creativity</title>
    <updated>2018-09-30T12:00:00Z</updated>
    <published>2018-09-30T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/opinion/logic-and-creativity.html"/>
    <content type="html">&lt;p&gt;Recently I filled in a survey about the shape I see the the year as
when imagining it. This is a topic I find interesting since my own
experience when asking people this question is that it never fails to
give interesting answers and usually an interesting discussion
afterwards. I therefore took care to give detailed answers, and filled
out the various other questions of the survey as well as I could. The
final question, “Do you consider yourself more logically or creatively
thinking?”, made me sigh, however.&lt;/p&gt;
&lt;p&gt;The question was answerable with a five point scale reaching from
“Logical” to ”Creative”, as if these two properties were somehow
mutually exclusive, or at least that excellling in one of them would
hamper the other. I believe this oft repeated dichotomy is false, and I
would like to elaborate a bit on why I think it is so.&lt;/p&gt;
&lt;p&gt;First of all, the two concepts “being logical” and “being creative”
do not immediately contradict each other by any definition of terms. For
instance, we could define “being creative“ loosely as “being able to
come up with novel, and interesting or useful, things” — be they
physical objects or ideas. And then let “being logical” mean “being able
to understand a system and follow its rules”. A toy example would be
that a creative person can craft a table, while a logical one would be
able to follow IKEA’s instructions for assembling a table. There is
ofcourse no reason a person cannot do both. But can anything more
meaningful be said about the connection between these two
properties?&lt;/p&gt;
&lt;p&gt;One thing one could say, with reasonable certainty, is that these two
properties are fundamental characterstics of human beings. Our whole
society is steaming with new ideas, new craftings, and as far as we can
tell, it has been like this for our entire history. At the same time, we
find that people quickly understand the rules of their environment and
adapt to these. In fact, it seems hard to imagine our species would have
reached its dominance, for better or worse, without it.&lt;/p&gt;
&lt;p&gt;Another thing, on which I am sure most would agree, is that most
humans thrive both when they can creative and when they can be logical.
Remark that I am not claiming that any person would enjoy any creative
endeavour, or to follow any system. Just that there for any person are
creative endeavours they would enjoy undertaking, and that there are
systems they would enjoy following. Creativity seem for instance to be
essential to humour, as jokes easily get old. While following rules is
key to most peoples wellbeing, as it gives them some measure of
predictability of their existence.&lt;/p&gt;
&lt;p&gt;This brings us the the interaction between the two notions. Because,
one of the ultimate creative endeavours is the construction of new
systems of rules to follow. This is a creative undertaking which has
being logical is a prerequisite, but which is the exact oposite of
stereo types of &lt;em&gt;both&lt;/em&gt; properties.&lt;/p&gt;
&lt;p&gt;One the one hand, constructing the rules is the oposite of the idea
that creativity is about not following rules. Not only do you have to
follow the rules to understand the system you are constructing, but you
also, implicitly follow the laws of logic when constructing your rules.
On the other hand, this defies the idea that “being logical” implies
following any rules blindly, since by creating new rules you have to
take back and reason about consequences of the rules.&lt;/p&gt;
&lt;p&gt;Mathematics is good example of an activity which essentially uses
both our creativity and ability to be logical. It is easy to see how the
latter plays a part, since mathematicians all play by the rules of
mathematical reasoning. But built in to that system is the ability to
define new concepts&lt;a href="#fn1" class="footnote-ref" id="fnref1"
role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;, and finding new mathematical
objects&lt;a href="#fn2" class="footnote-ref" id="fnref2"
role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; fitting into those concepts — a
process which is extremely creative. Mathematical creativiy is an
extreme example of an effect that is noticed also in art, namely that
limitations, that is rules, induce creativity.&lt;/p&gt;
&lt;p&gt;The final claim I want to make, which I find the most likely to be
controversial, is that when given the freedom humans will tend to
maximise both their creativity and ability to act logically, and that
reductions in either is indicative of a lack of freedom. For instance,
in a totalitarian society a person might simultaneously believe that he
lives in a great society, while at the same time being aware of the
suffering of the people in it, including him own — a clear logical
fallacy. In contrast, a person who has secured his basic needs, and
still has time to spare, will often take up a creative activity in this
time.&lt;/p&gt;
&lt;p&gt;In conclusion, we see that to put up a dichotomy between logical and
creative ability, like this survey did, does little service to either,
and that they are best seen as complementary, and fundamental, abilties
of human beings.&lt;/p&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document"
role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;Say, structures or theorems.&lt;a href="#fnref1"
class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2"&gt;&lt;p&gt;Say, instances of structures or proofs of theorems.&lt;a
href="#fnref2" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/opinion/syntax-highlighting.html</id>
    <title>How I program without syntax highlighting</title>
    <updated>2018-09-30T12:00:00Z</updated>
    <published>2018-09-30T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/opinion/syntax-highlighting.html"/>
    <content type="html">&lt;p&gt;For more than a year I have been without syntax highlighting. My
editor of choice, acme, simply does not have it and I actually prefer it
that way. Some would explain this as an instance of the Stockholm
syndrome, or some strange form of hipsterism. However, I think there are
some valid advantages to not colouring our texts, and so I will put them
forth.&lt;/p&gt;
&lt;h2 id="what-syntax-highlighting-is-good-for"&gt;What syntax highlighting
is good for&lt;/h2&gt;
&lt;p&gt;Some people &lt;a
href="http://en.wikipedia.org/wiki/synesthesia"&gt;perceive numbers and
letters as coloured&lt;/a&gt;, and can use this ability to solve some tasks
quicker. So initially, giving everyone synesthesia for free using syntax
highlighting seems like it should improve our ability to understand code
quickly. I do think it does give some speedup in checking wether there
are syntax mistakes in the code. The classic example is some sneaky
comment errors like this one:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  // Initialise
  for (i=0;i&amp;lt;3;++i) {
    /* Do initialisation here!
    niftyConfig = 1;
    funkyValue = 2;
  }

  // Run forever
  for (;;) {
   /* So, this is where we do stuff! */
  ...
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Syntax highlighting is not the only way of telling that your
parenthesis, quotes and comments are matched up. In Acme I double click
on the outmost marker to check that it has a match. This gives the added
benefit that the region is selected if I wish to make edits to it. This
is an active action on my part, because usually I know where my
parentheisis go and do not need any help.&lt;a href="#fn1"
class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For most part syntax is not the most challenging part of programming,
and I have yet to run into troubles where I could not spot my syntax
errors. I usually program in a tight loop of writing, compiling and
testing, meaning that any syntax related mistakes are probably in the
most recently edited region and are easy to spot.&lt;/p&gt;
&lt;h2 id="the-beauty-of-code"&gt;The beauty of code&lt;/h2&gt;
&lt;p&gt;The first thing one thinks when going from highlighted to
unhighlighted code might be «This code is just a grey mash of symbols».
Though, this sensation quickly fades as one gets engaged in the code.
This “getting in to the groove”-part of the programming session is
remarkably short, and afterwards code is more readable than English.&lt;/p&gt;
&lt;p&gt;If the code is neatly organised, the «grey mash» quickly crystalises
into a beautiful little universe of logically connected parts; each
standing by it self, on its own line or in its own scope, but
referencing each other in clear and beautiful ways. However, if the code
is disorganised, with commented-out code, overly long lines and all,
then the «grey mash» shape-shifts to a minefield in rough terrain, with
craters and rocks obscruing the view.&lt;/p&gt;
&lt;p&gt;What I am saying is that, coding without the syntax highlighting
makes me much more sensitive to code “beauty”. This means that I avoid
anti-patterns like having too long lines, or commenting out code. When
my syntax highligher would make comments grey, I would frequently have
two or three versions of a function in the comments while writing, and
have to remind my self go clean the mess up. Now, I much rather copy the
old version to a scratch file or buffer before making revisions. This
keeps the code beautiful and easy to read.&lt;/p&gt;
&lt;h2 id="supports-all-languages"&gt;Supports all languages&lt;/h2&gt;
&lt;p&gt;Once syntax highlighting is gone, you no longer priviledge the class
of languages for which there exists a syntax highlighting. As a
programmer you will not spend time looking for a highlighter, and
configuring it for your preferences. Since I work a lot in a language
called Agda, which is a language with absent support in most editors,
this is important to me.&lt;/p&gt;
&lt;p&gt;Editors in general suffer from over-configurability. Humans in
general, and programmers in particular, like to tinker. Once you start
tinkering on the configuration file of your editor, it easily gets in
the way of what you actually were supposed to do. Syntax highlighting
especially invites to these distractions as it is in your face while
programming. If something about it annoys you, you are bound to notice
while programming.&lt;/p&gt;
&lt;p&gt;Supporting all languages equally future-proves the editor, because
who knows which language we will use in ten years? Not to mention that
syntax in a given language changes between version: new keywords added,
new function syntax, and λ-abstractions added.&lt;/p&gt;
&lt;p&gt;This also clears the distinction between the editor and other tools.
The editor lets you edit code, it does not parse it and check its
syntax. If it does, it is bound to do it wrong when the language
changes, and require continual maintainance.&lt;/p&gt;
&lt;h2 id="other-people-have-written-about-this-before"&gt;Other people have
written about this before&lt;/h2&gt;
&lt;ol type="1"&gt;
&lt;li&gt;&lt;a
href="http://www.linusakesson.net/programming/syntaxhighlighting/"&gt;Linus
Åkesson&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href="https://web.archive.org/web/20170319161308/https://www.kyleisom.net/blog/2012/10/17/syntax-off/"&gt;Kyle
Isom&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;section id="footnotes" class="footnotes footnotes-end-of-document"
role="doc-endnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;Some programming languages, such as Agda, has comment
nesting as part of their syntax and thus examples similar to the above
would not be valid syntax. This is arguably the sane approach.&lt;a
href="#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</content>
  </entry>
  <entry>
    <id>https://hakon.gylterud.net/review/taskwarrior.html</id>
    <title>TaskWarrior</title>
    <updated>2018-05-01T12:00:00Z</updated>
    <published>2018-05-01T12:00:00Z</published>
    <link rel="alternate" type="text/html" href="https://hakon.gylterud.net/review/taskwarrior.html"/>
    <content type="html">&lt;p&gt;While the name sounds agressive, the program itself is actually quite
pleasant and useful. &lt;a href="https://taskwarrior.org/"&gt;TaskWarrior&lt;/a&gt;
is &lt;em&gt;a todo-list manager with a command line interface&lt;/em&gt;. The
command itself is just &lt;code&gt;task&lt;/code&gt;, so even pacifists can use
it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Metadata&lt;/em&gt; is where TaskWarrior has its strength. If you take
the time to type in a bit of meta-data on each task, there is much you
can do with it in TaskWarrior. For instance, based on information such
as tags and due dates, it computes the urgency of each task to help the
user chosing what to do next.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://taskwarrior.org/docs/"&gt;online documentation&lt;/a&gt;
of TaskWarrior is very readable, and they have a lot of examples. The
man page is a convenient refence, but not really suited for learning how
to use it. So you need to go online to get started.&lt;/p&gt;
&lt;h2 id="ontology"&gt;Ontology&lt;/h2&gt;
&lt;p&gt;TaskWarrior is not minimalistic, but its ontology is not very
difficult: There are tasks and they have attributes, such as tags, due
dates or priority. The tasks are presented in reports, which show a
selection of attributes for a selected set of tasks. For instance,
&lt;code&gt;task ready&lt;/code&gt; shows tasks which are currently scheduled to be
done, sorted by urgency. Another important attribute is
&lt;code&gt;depend&lt;/code&gt; which allows you to express dendencies&lt;/p&gt;
&lt;p&gt;There is also support for user defined attributes (in the
documentation often hidden behind the acronym UDA). This means that you
can assign more semantics to your tasks, and possibly write your own
scripts which interact with TaskWarrior.&lt;/p&gt;
&lt;h2 id="pitfalls"&gt;Pitfalls&lt;/h2&gt;
&lt;p&gt;While TaskWarrior is not very difficult to learn, it might be
difficult to use effectively. Here are some of the pitfals.&lt;/p&gt;
&lt;p&gt;The first pitfall with any todo-list is just forgetting about it.
Taskwarrior lives on the command line and will not pop up in your face
every time you open the computer. It mighth therefore be easy to forget
about it completely.&lt;/p&gt;
&lt;p&gt;One way to avoid forgetting about it is to make a cronjob which
e-mails you, say every workday, a list of remaining tasks. This makes
TaskWarrior into a kind of personal assistant who every morning recites
the tasks you have planned for the day.&lt;/p&gt;
&lt;p&gt;Aother pitfall is the snowball effect. It is easy to get carried away
with planning lots of activities, thinking that just because you can
write it all on a list, you will be able to complete it all. Then you
notice there are a few things you are not do in time for the deadline
you set. Then you postpone it, start the next batch of tasks, again not
completing everything. And suddenly there is an avalanche of things on
your todo-lists, and you become demotivated by the sight of the
list.&lt;/p&gt;
&lt;p&gt;TaskWarrior has some features to remidy this. The attributes
&lt;code&gt;wait&lt;/code&gt; and &lt;code&gt;schedule&lt;/code&gt; allows you to keep tasks
which you do not have to do right now out of view. Taking
&lt;code&gt;schedule&lt;/code&gt; as an example: You can schedule a task
(e.g. &lt;code&gt;task add Do something. schedule:tuesday&lt;/code&gt;) and it will
not appear in the &lt;code&gt;task ready&lt;/code&gt; report until Tuesday. This
helps reduce clutter. Tasks which you think “Oh, I should do that…
someday.” you can actually &lt;code&gt;schedule:someday&lt;/code&gt; and it will be
kept, but not be in your face while you are doing more urgent
things.&lt;/p&gt;</content>
  </entry>
</feed>
