<?xml version='1.0' encoding='utf-8'?>
<?xml-stylesheet type="text/xsl" href="/sheet.xsl"?><rss version="2.0"><channel><title>Planet Haskell</title><link>http://planet.haskell.org/</link><language>en</language><description>Planet Haskell - http://planet.haskell.org/</description><item><title>Mark Jason Dominus: Documentation is a message in a bottle</title><guid isPermaLink="false">tag:,2026:/tech/gpt/documentation-wins</guid><link>https://blog.plover.com/tech/gpt/documentation-wins.html</link><description>&lt;p&gt;Our company is
going to a convention later this month, and they will have a booth with
big TV screens showing statistics that update in real time.  My job is
to write the backend server that delivers the statistics.&lt;/p&gt;

&lt;p&gt;I read over the documents that the product people had written up about
what was wanted, asked questions, got answers, and then turned the
original two-line ticket into a three-page ticket that said what
should be done and how.  I intended to do the ticket myself, but it's
good practice to write all this stuff down, for many reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Writing things down forces me to think them through carefully and
realize what doesn't make sense or what I still don't understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I forget things easily and this will keep the plan where I can find it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I might get sick, and if someone else has to pick up the project
this might help them understand what I was doing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If my boss gets worried that all I do is post on 4chan all day, this
is tangible work product that proves I did something else that might
have enhanced shareholder value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If I'm tempted to spend the day posting on 4chan, and then to later
&lt;em&gt;claim&lt;/em&gt; I spent the time planning the project, I might fool my boss.
But without that tangible work product, I won't be able to fool
&lt;em&gt;myself&lt;/em&gt;, and that's more important.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conversely if I later think back and ask “What was I doing the week
of March 2?” I might be tempted to imagine that all I did was post
on 4chan.  But the three pages of ticket description will prove to
me that I am not just a lazy slacker.  &lt;a href="https://blog.plover.com/misc/evaluation.html"&gt;This is a real problem for
me&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In principle, a future person going back to extend the work might
find this helpful documentation of what was done and why.  Does this
ever really happen?  I don't know, but it might.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I like writing because writing is fun.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few days after I wrote the ticket, something unexpected happened.
It transpired that person who was to build the front-end consumer of
my statistics would not be a professional programmer.  It would be the
company's Head of Product, a very smart woman named Amanda. The actual
code would be written by Claude, under her supervision.&lt;/p&gt;

&lt;p&gt;I have never done anything like this before, and I would not have
wanted to try it on a short deadline, but there is some slack in the
schedule and it seemed a worthwhile and exciting experiment.&lt;/p&gt;

&lt;p&gt;Amanda shared some screencaps of her chats with Claude about the
project, and I suggested:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When you get a chance, please ask Claude to write out a Markdown
  file memorializing all this.  Tell it that you're going to give it
  to the backend programmer for discussion, so more detail is better.
  When it's ready, send it over.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude immediately produced a nine-page, 14-part memo and a half-page
overview.  I spent a couple of hours reviewing it and marking it up.&lt;/p&gt;

&lt;p&gt;It became immediately clear that Claude and I had very similar ideas
about how the project should go and how the front and back ends would
hook up.  So similar that I asked Angela:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It looks like maybe you started it off by feeding it my ticket
  description.  Is that right? &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;She said yes, she had.  She had also fed it the original product
documents I had read.&lt;/p&gt;

&lt;p&gt;I was delighted.  I had had many reasons for writing detailed ticket
descriptions before, but the most plausible ones were aimed back at
myself.&lt;/p&gt;

&lt;p&gt;The external consumers of the documentation all seemed somewhat
unlikely.  The person who would extend the project in the future
probably didn't exist, and if they did they probably wouldn't have
thought to look at my notes.  Same for the hypothetical person who
would take over when I got sick.  My boss probably isn't checking up
on me by looking at my ticketing history.  Still, I like to document
these things for my own benefit, and also just in case.&lt;/p&gt;

&lt;p&gt;But now, because I had written the project plan, it was available for
consumption when an unexpected consumer turned up!  Claude and I were
able to rapidly converge on the design of the system, because Amanda
had found my notes and cleverly handed them to Claude.  Suddenly one
of those unlikely-seeming external reasons materialized!&lt;/p&gt;

&lt;p&gt;On Mastodon I keep seeing programmers say how angry it makes
them that people are willing to write detailed &lt;code&gt;CLAUDE.md&lt;/code&gt; and
&lt;code&gt;PROJECT.md&lt;/code&gt; files for Claude to use, but they weren't willing to
write them for their coworkers.  (They complain about this as if this
is somehow the fault of the AI, rather than of the people who failed
in the past to write documentation for their coworkers.)&lt;/p&gt;

&lt;p&gt;The obvious answer to the question of why people are willing to write
documentation for Claude but not for their coworkers is that the
author can count on Claude to &lt;em&gt;read&lt;/em&gt; the documentation, whereas it's a
rare coworker who will look at it attentively.&lt;/p&gt;

&lt;p&gt;Rik Signes points out there's a less obvious but more likely answer:
your coworkers will remember things if you just tell them, but Claude
forgets everything every time.  If you want Claude to remember
something, you have to write it down.  So people using Claude do write
things down, because otherwise they have to say them over and over.&lt;/p&gt;

&lt;p&gt;And there's a happy converse to the complaint that most programmers
don't bother to write documentation.  It means that people like me,
professionals who &lt;em&gt;have&lt;/em&gt; always written meticulous documentation, are
now reaping new benefits from that always valuable practice.&lt;/p&gt;

&lt;p&gt;Not everything is going to get worse.  Some things will get better.&lt;/p&gt;</description><pubDate>Thu, 05 Mar 2026 16:07:00 +0000</pubDate><author>mjd@plover.com (Mark Dominus)</author><ns0:encoded xmlns:ns0="http://purl.org/rss/1.0/modules/content/">&lt;td class="mainsection" bgcolor="#fdfdfd" morss_own_score="5.7309417040358746" morss_score="66.65518412827831"&gt;
&lt;br&gt;
&lt;span&gt;Thu, 05 Mar 2026&lt;/span&gt;
&lt;p&gt;
&lt;a href="https://blog.plover.com/tech/gpt/documentation-wins.html"&gt;Documentation is a message in a bottle&lt;/a&gt;
&lt;br&gt;
&lt;/p&gt;&lt;p&gt;Our company is
going to a convention later this month, and they will have a booth with
big TV screens showing statistics that update in real time.  My job is
to write the backend server that delivers the statistics.&lt;/p&gt;
&lt;p&gt;I read over the documents that the product people had written up about
what was wanted, asked questions, got answers, and then turned the
original two-line ticket into a three-page ticket that said what
should be done and how.  I intended to do the ticket myself, but it's
good practice to write all this stuff down, for many reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Writing things down forces me to think them through carefully and
realize what doesn't make sense or what I still don't understand.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I forget things easily and this will keep the plan where I can find it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I might get sick, and if someone else has to pick up the project
this might help them understand what I was doing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If my boss gets worried that all I do is post on 4chan all day, this
is tangible work product that proves I did something else that might
have enhanced shareholder value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If I'm tempted to spend the day posting on 4chan, and then to later
&lt;em&gt;claim&lt;/em&gt; I spent the time planning the project, I might fool my boss.
But without that tangible work product, I won't be able to fool
&lt;em&gt;myself&lt;/em&gt;, and that's more important.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conversely if I later think back and ask “What was I doing the week
of March 2?” I might be tempted to imagine that all I did was post
on 4chan.  But the three pages of ticket description will prove to
me that I am not just a lazy slacker.  &lt;a href="https://blog.plover.com/misc/evaluation.html"&gt;This is a real problem for
me&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In principle, a future person going back to extend the work might
find this helpful documentation of what was done and why.  Does this
ever really happen?  I don't know, but it might.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I like writing because writing is fun.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A few days after I wrote the ticket, something unexpected happened.
It transpired that person who was to build the front-end consumer of
my statistics would not be a professional programmer.  It would be the
company's Head of Product, a very smart woman named Amanda. The actual
code would be written by Claude, under her supervision.&lt;/p&gt;
&lt;p&gt;I have never done anything like this before, and I would not have
wanted to try it on a short deadline, but there is some slack in the
schedule and it seemed a worthwhile and exciting experiment.&lt;/p&gt;
&lt;p&gt;Amanda shared some screencaps of her chats with Claude about the
project, and I suggested:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When you get a chance, please ask Claude to write out a Markdown
  file memorializing all this.  Tell it that you're going to give it
  to the backend programmer for discussion, so more detail is better.
  When it's ready, send it over.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude immediately produced a nine-page, 14-part memo and a half-page
overview.  I spent a couple of hours reviewing it and marking it up.&lt;/p&gt;
&lt;p&gt;It became immediately clear that Claude and I had very similar ideas
about how the project should go and how the front and back ends would
hook up.  So similar that I asked Angela:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It looks like maybe you started it off by feeding it my ticket
  description.  Is that right? &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;She said yes, she had.  She had also fed it the original product
documents I had read.&lt;/p&gt;
&lt;p&gt;I was delighted.  I had had many reasons for writing detailed ticket
descriptions before, but the most plausible ones were aimed back at
myself.&lt;/p&gt;
&lt;p&gt;The external consumers of the documentation all seemed somewhat
unlikely.  The person who would extend the project in the future
probably didn't exist, and if they did they probably wouldn't have
thought to look at my notes.  Same for the hypothetical person who
would take over when I got sick.  My boss probably isn't checking up
on me by looking at my ticketing history.  Still, I like to document
these things for my own benefit, and also just in case.&lt;/p&gt;
&lt;p&gt;But now, because I had written the project plan, it was available for
consumption when an unexpected consumer turned up!  Claude and I were
able to rapidly converge on the design of the system, because Amanda
had found my notes and cleverly handed them to Claude.  Suddenly one
of those unlikely-seeming external reasons materialized!&lt;/p&gt;
&lt;p&gt;On Mastodon I keep seeing programmers say how angry it makes
them that people are willing to write detailed &lt;code&gt;CLAUDE.md&lt;/code&gt; and
&lt;code&gt;PROJECT.md&lt;/code&gt; files for Claude to use, but they weren't willing to
write them for their coworkers.  (They complain about this as if this
is somehow the fault of the AI, rather than of the people who failed
in the past to write documentation for their coworkers.)&lt;/p&gt;
&lt;p&gt;The obvious answer to the question of why people are willing to write
documentation for Claude but not for their coworkers is that the
author can count on Claude to &lt;em&gt;read&lt;/em&gt; the documentation, whereas it's a
rare coworker who will look at it attentively.&lt;/p&gt;
&lt;p&gt;Rik Signes points out there's a less obvious but more likely answer:
your coworkers will remember things if you just tell them, but Claude
forgets everything every time.  If you want Claude to remember
something, you have to write it down.  So people using Claude do write
things down, because otherwise they have to say them over and over.&lt;/p&gt;
&lt;p&gt;And there's a happy converse to the complaint that most programmers
don't bother to write documentation.  It means that people like me,
professionals who &lt;em&gt;have&lt;/em&gt; always written meticulous documentation, are
now reaping new benefits from that always valuable practice.&lt;/p&gt;
&lt;p&gt;Not everything is going to get worse.  Some things will get better.&lt;/p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;/td&gt;
</ns0:encoded></item><item><title>Mark Jason Dominus: Bo Diddley</title><guid isPermaLink="false">tag:,2026:/lang/etym/Bo-Diddley</guid><link>https://blog.plover.com/lang/etym/Bo-Diddley.html</link><description>&lt;p&gt;Bo Diddley's cover of "Sixteen Tons" sounds very much like one of my
favorites, "Can't Judge A Book By Its Cover".  It's interesting to
compare.&lt;/p&gt;

&lt;p&gt;Thinking on that it suddenly occured to me that his name might have
been a play on “diddley bow”, which is a sort of homemade one-stringed
zither.  The player uses a bottle as a bridge for the string, and
changes the pitch by sliding the bottle up and down.  When you hear
about blues artists whose first guitars were homemade, this is often
what was meant: it wasn't a six-string guitar, it was a diddley bow.&lt;/p&gt;

&lt;p&gt;But it's not clear that Bo Diddley &lt;em&gt;did&lt;/em&gt; play his name on the diddley
bow.  "Diddly" also means something insignificant or of little value,
and might have been a disparaging nickname he received in his
youth. (It also appears in the phrase "diddly squat").  Maybe that's
also the source of the name of the diddley bow.&lt;/p&gt;</description><pubDate>Tue, 03 Mar 2026 16:39:00 +0000</pubDate><author>mjd@plover.com (Mark Dominus)</author></item><item><title>Donnacha Oisín Kidney: Monuses and Heaps</title><guid isPermaLink="true">https://doisinkidney.com/posts/2026-03-03-monus-heaps.html</guid><link>https://doisinkidney.com/posts/2026-03-03-monus-heaps.html</link><description>&lt;div class="info"&gt;
    Posted on March  3, 2026
&lt;/div&gt;
&lt;div class="info"&gt;
    
&lt;/div&gt;
&lt;div class="info"&gt;
    
        Tags: &lt;a href="https://doisinkidney.com/tags/Haskell.html" rel="tag" title="All pages tagged 'Haskell'."&gt;Haskell&lt;/a&gt;
    
&lt;/div&gt;

&lt;p&gt;This post is about a simple algebraic structure that I have found
useful for algorithms that involve searching or sorting based on some
ordered weight. I used it a bit in a pair of papers on graph search
&lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;; &lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_formalising_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;, and more recently I used it to
implement a version of the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Phases&lt;/span&gt;&lt;/code&gt; type
&lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-easterly_functions_2019"&gt;Easterly
2019&lt;/a&gt;)&lt;/span&gt; that supported arbitrary keys, inspired by some work by
BlÃ¶ndal &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-blondal_generalized_2025"&gt;2025a&lt;/a&gt;; &lt;a href="https://doisinkidney.com/rss.xml#ref-blondal_phases_2025"&gt;2025b&lt;/a&gt;)&lt;/span&gt;
and &lt;span class="citation"&gt;Visscher
(&lt;a href="https://doisinkidney.com/rss.xml#ref-visscher_phases_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The algebraic structure in question is a &lt;em&gt;monus&lt;/em&gt;, which is a
kind of monoid that supports a partial subtraction operation (that
subtraction operation, denoted by the symbol âˆ¸, is itself often called a
â€œmonusâ€�). However, before giving the full definition of the structure,
let me first try to motivate its use. The context here is heap-based
algorithms. For the purposes of this post, a heap is a tree that obeys
the â€œheap propertyâ€�; i.e.Â every node in the tree has some â€œweightâ€�
attached to it, and every parent node has a weight less than or equal to
the weight of each of its children. So, for a tree like the
following:&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb1-1" tabindex="-1"&gt;&lt;/a&gt;   â”Œd&lt;/span&gt;
&lt;span id="cb1-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb1-2" tabindex="-1"&gt;&lt;/a&gt; â”Œbâ”¤&lt;/span&gt;
&lt;span id="cb1-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb1-3" tabindex="-1"&gt;&lt;/a&gt;aâ”¤ â””e&lt;/span&gt;
&lt;span id="cb1-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb1-4" tabindex="-1"&gt;&lt;/a&gt; â””c&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The heap property is satisfied when
&amp;lt;semantics&amp;gt;aâ‰¤b&amp;lt;annotation encoding="application/x-tex"&amp;gt;a \leq b&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;,
&amp;lt;semantics&amp;gt;aâ‰¤c&amp;lt;annotation encoding="application/x-tex"&amp;gt;a \leq c&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;,
&amp;lt;semantics&amp;gt;bâ‰¤d&amp;lt;annotation encoding="application/x-tex"&amp;gt;b \leq d&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;,
and
&amp;lt;semantics&amp;gt;bâ‰¤e&amp;lt;annotation encoding="application/x-tex"&amp;gt;b \leq e&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;.&lt;/p&gt;
&lt;p&gt;Usually, we also want our heap structure to have an operation like
&lt;code class="sourceCode haskell"&gt;&lt;span class="ot"&gt;popMin ::&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (v, &lt;span class="dt"&gt;Heap&lt;/span&gt; k v)&lt;/code&gt;
that returns the least-weight value in the heap paired with the rest of
the heap. If this operation is efficient, we can use the heap to
efficiently implement sorting algorithms, graph search, etc. In fact,
let me give the whole basic interface for a heap here:&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="https://doisinkidney.com/rss.xml#cb2-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;popMin ::&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (v, &lt;span class="dt"&gt;Heap&lt;/span&gt; k v)&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb2-2" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;insert ::&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb2-3" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;empty  ::&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using these functions itâ€™s not hard to see how we can implement a
sorting algorithm:&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="https://doisinkidney.com/rss.xml#cb3-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sortOn ::&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb3-2" tabindex="-1"&gt;&lt;/a&gt;sortOn k &lt;span class="ot"&gt;=&lt;/span&gt; unfoldr popMin &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;foldr&lt;/span&gt; (\x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; insert (k x) x) empty&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The monus becomes relevant when the weight involved is some kind of
&lt;em&gt;monoid&lt;/em&gt;. This is quite a common situation: if we were using the
heap for graph search (least-cost paths or something), we would expect
the weight to correspond to path costs, and we would expect that we can
add the costs of paths in a kind of monoidal way. Furthermore, we would
probably expect the monoidal operations to relate to the order in some
coherent way. A monus &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-amer_equationally_1984"&gt;Amer
1984&lt;/a&gt;)&lt;/span&gt; is an ordered monoid where the order itself can be
defined &lt;em&gt;in terms&lt;/em&gt; of the monoidal operations&lt;a class="footnote-ref" href="https://doisinkidney.com/rss.xml#fn1" id="fnref1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&amp;lt;semantics&amp;gt;xâ‰¤yâ‡”âˆƒz.y=xâ€¢z&amp;lt;annotation encoding="application/x-tex"&amp;gt; x \leq y \iff \exists z. \; y = x \bullet z &amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;&lt;/p&gt;
&lt;p&gt;I read this definition as saying
â€œ&amp;lt;semantics&amp;gt;x&amp;lt;annotation encoding="application/x-tex"&amp;gt;x&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
is less than
&amp;lt;semantics&amp;gt;y&amp;lt;annotation encoding="application/x-tex"&amp;gt;y&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
iff there is some
&amp;lt;semantics&amp;gt;z&amp;lt;annotation encoding="application/x-tex"&amp;gt;z&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
that &lt;em&gt;fits between&lt;/em&gt;
&amp;lt;semantics&amp;gt;x&amp;lt;annotation encoding="application/x-tex"&amp;gt;x&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
and
&amp;lt;semantics&amp;gt;y&amp;lt;annotation encoding="application/x-tex"&amp;gt;y&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;â€�.
In other words, the &lt;em&gt;gap&lt;/em&gt; between
&amp;lt;semantics&amp;gt;x&amp;lt;annotation encoding="application/x-tex"&amp;gt;x&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
and
&amp;lt;semantics&amp;gt;y&amp;lt;annotation encoding="application/x-tex"&amp;gt;y&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
has to exist, and it is equal to
&amp;lt;semantics&amp;gt;z&amp;lt;annotation encoding="application/x-tex"&amp;gt;z&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;.&lt;/p&gt;
&lt;p&gt;Notice that this order definition wonâ€™t work for groups like
&amp;lt;semantics&amp;gt;(â„¤,+,0)&amp;lt;annotation encoding="application/x-tex"&amp;gt;(\mathbb{Z},+,0)&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;.
For a group, we can &lt;em&gt;always&lt;/em&gt; find some
&amp;lt;semantics&amp;gt;z&amp;lt;annotation encoding="application/x-tex"&amp;gt;z&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
that will fit the existential (specifically,
&amp;lt;semantics&amp;gt;z=(âˆ’x)â€¢y&amp;lt;annotation encoding="application/x-tex"&amp;gt;z = (- x) \bullet y&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;).
Monuses, then, tend to be positive monoids: in fact, many monuses are
the positive cones of some group
(&amp;lt;semantics&amp;gt;(â„•,+,0)&amp;lt;annotation encoding="application/x-tex"&amp;gt;(\mathbb{N},+,0)&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
is the positive cone of
&amp;lt;semantics&amp;gt;(â„¤,+,0)&amp;lt;annotation encoding="application/x-tex"&amp;gt;(\mathbb{Z},+,0)&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;).&lt;/p&gt;
&lt;p&gt;We can derive a lot of useful properties from this basic structure.
For example, if the order above is total, then we can derive the binary
subtraction operator mentioned above:&lt;/p&gt;
&lt;p&gt;&amp;lt;semantics&amp;gt;xâˆ¸y={z,if yâ‰¤x and x=yâ€¢z0,otherwise.&amp;lt;annotation encoding="application/x-tex"&amp;gt; x âˆ¸ y =
\begin{cases}
z, &amp;amp; \text{if } y \leq x \text{ and } x = y \bullet z  \\
0, &amp;amp; \text{otherwise.}
\end{cases}
&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;&lt;/p&gt;
&lt;p&gt;If we require the underlying monoid to be commutative, and we further
require the derived order to be total and antisymmetric, we get the
particular flavour of monus I worked with in a pair of papers on graph
search &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;; &lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_formalising_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;. In this post I will actually be
working with a weakened form of the algebra that I will define
shortly.&lt;/p&gt;
&lt;p&gt;Getting back to our heap from above, with this new order defined, we
can see that the heap property actually tells us something about the
makeup of the weights in the tree. Instead of every child just having a
weight equal to some arbitrary quantity, the heap property tells us that
each child weight has to be made up of the combination of its parentâ€™s
weight and some difference.&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="https://doisinkidney.com/rss.xml#cb4-1" tabindex="-1"&gt;&lt;/a&gt;   â”Œd              â”Œbâ€¢(dâˆ¸b)&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb4-2" tabindex="-1"&gt;&lt;/a&gt; â”Œbâ”¤       â”Œaâ€¢(bâˆ¸a)â”¤&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb4-3" tabindex="-1"&gt;&lt;/a&gt;aâ”¤ â””e  &lt;span class="ot"&gt;=&lt;/span&gt;  aâ”¤       â””bâ€¢(eâˆ¸b)&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb4-4" tabindex="-1"&gt;&lt;/a&gt; â””c        â””aâ€¢(câˆ¸a)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This observation gives us an opportunity for a different
representation: instead of storing the full weight at each node, we
could instead just store the difference.&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="https://doisinkidney.com/rss.xml#cb5-1" tabindex="-1"&gt;&lt;/a&gt;     â”Œdâˆ¸b&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb5-2" tabindex="-1"&gt;&lt;/a&gt; â”Œbâˆ¸aâ”¤&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb5-3" tabindex="-1"&gt;&lt;/a&gt;aâ”¤   â””eâˆ¸b&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb5-4" tabindex="-1"&gt;&lt;/a&gt; â””câˆ¸a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Just in terms of data structure design, I prefer this version: if we
wanted to write down a type of heaps using the previous design, we would
first define the type of trees, and then separately write a predicate
corresponding to the heap property. With this design, it is impossible
to write down a tree that &lt;em&gt;doesnâ€™t&lt;/em&gt; satisfy the heap
property.&lt;/p&gt;
&lt;p&gt;More practically, though, using this algebraic structure when working
with heaps enables some optimisations that might be difficult to
implement otherwise. The strength of this representation is that it
allows for efficient relative and global computation: now, if we wanted
to add some quantity to every weight in the tree, we can do it just by
adding the weight to the root node.&lt;/p&gt;
&lt;h1 id="monuses-in-haskell"&gt;Monuses in Haskell&lt;/h1&gt;
&lt;p&gt;To see some examples of how to use this pattern, letâ€™s first write a
class for Haskell monuses:&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="https://doisinkidney.com/rss.xml#cb6-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; (&lt;span class="dt"&gt;Semigroup&lt;/span&gt; a, &lt;span class="dt"&gt;Ord&lt;/span&gt; a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb6-2" tabindex="-1"&gt;&lt;/a&gt;  (âˆ¸)&lt;span class="ot"&gt; ::&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Youâ€™ll notice that weâ€™re requiring semigroup here, not monoid. Thatâ€™s
because one of the nice uses of this pattern actually works with a
weakening of the usual monus algebra; this weakening only requires
semigroup, and the following two laws.&lt;/p&gt;
&lt;p&gt;&amp;lt;semantics&amp;gt;xâ‰¤yâŸ¹xâ€¢(yâˆ¸x)=yxâ‰¤yâŸ¹zâ€¢xâ‰¤zâ€¢y&amp;lt;annotation encoding="application/x-tex"&amp;gt; x \leq y \implies x \bullet (y âˆ¸ x) = y
\quad \quad \quad \quad \quad
x \leq y \implies z \bullet x \leq z \bullet y &amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;&lt;/p&gt;
&lt;p&gt;A straightforward monus instance is the following:&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb7-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; (&lt;span class="dt"&gt;Num&lt;/span&gt; a, &lt;span class="dt"&gt;Ord&lt;/span&gt; a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; (&lt;span class="dt"&gt;Sum&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb7-2" tabindex="-1"&gt;&lt;/a&gt;  (âˆ¸) &lt;span class="ot"&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;h1 id="pairing-heaps-in-haskell"&gt;Pairing Heaps in Haskell&lt;/h1&gt;
&lt;p&gt;Next, letâ€™s look at a simple heap implementation. I will always go
for pairing heaps &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-fredman_pairing_1986"&gt;Fredman et al. 1986&lt;/a&gt;)&lt;/span&gt; in Haskell; they
are extremely simple to implement, and (as long as you donâ€™t have
significant persistence requirements) their performance seems to be the
best of the available pointer-based heaps &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-larkin_backtobasics_2013"&gt;Larkin, Sen,
and Tarjan 2013&lt;/a&gt;)&lt;/span&gt;. Here is the type definition:&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="https://doisinkidney.com/rss.xml#cb8-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; k v &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;k v [&lt;span class="dt"&gt;Root&lt;/span&gt; k v]&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb8-2" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;type&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (&lt;span class="dt"&gt;Root&lt;/span&gt; k v)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Root&lt;/span&gt;&lt;/code&gt; is a
non-empty pairing heap; the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Heap&lt;/span&gt;&lt;/code&gt; type
represents possibly-empty heaps. The key function to implement is the
merging of two heaps; we can accomplish this as an implementation of the
semigroup &lt;code class="sourceCode haskell"&gt;&lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/code&gt;.&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="https://doisinkidney.com/rss.xml#cb9-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Semigroup&lt;/span&gt; (&lt;span class="dt"&gt;Root&lt;/span&gt; k v) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb9-2" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Root&lt;/span&gt; xk xv xs &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; yk yv ys&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb9-3" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;|&lt;/span&gt; xk &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; yk  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; xk xv (&lt;span class="dt"&gt;Root&lt;/span&gt; (yk âˆ¸ xk) yv ys &lt;span class="op"&gt;:&lt;/span&gt; xs)&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb9-4" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; yk yv (&lt;span class="dt"&gt;Root&lt;/span&gt; (xk âˆ¸ yk) xv xs &lt;span class="op"&gt;:&lt;/span&gt; ys)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The only difference between this and a normal pairing heap merge is
the use of &lt;code class="sourceCode haskell"&gt;âˆ¸&lt;/code&gt; in the key of the
child node (&lt;code class="sourceCode haskell"&gt;yk âˆ¸ xk&lt;/code&gt; and &lt;code class="sourceCode haskell"&gt;xk âˆ¸ yk&lt;/code&gt;). This difference ensures that
each child only holds the difference of the weight between itself and
its parent.&lt;/p&gt;
&lt;p&gt;Itâ€™s worth working out why the weakened monus laws above are all we
need in order to maintain the heap property on this structure.&lt;/p&gt;
&lt;p&gt;The rest of the methods are implemented the same as their
implementations on a normal pairing heap. First, we have the pairing
merge of a list of heaps, here given as an implementation of the
semigroup method &lt;code class="sourceCode haskell"&gt;sconcat&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="https://doisinkidney.com/rss.xml#cb10-1" tabindex="-1"&gt;&lt;/a&gt;  sconcat (x1 &lt;span class="op"&gt;:|&lt;/span&gt; []) &lt;span class="ot"&gt;=&lt;/span&gt; x1&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb10-2" tabindex="-1"&gt;&lt;/a&gt;  sconcat (x1 &lt;span class="op"&gt;:|&lt;/span&gt; [x2]) &lt;span class="ot"&gt;=&lt;/span&gt; x1 &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; x2&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb10-3" tabindex="-1"&gt;&lt;/a&gt;  sconcat (x1 &lt;span class="op"&gt;:|&lt;/span&gt; x2 &lt;span class="op"&gt;:&lt;/span&gt; x3 &lt;span class="op"&gt;:&lt;/span&gt; xs) &lt;span class="ot"&gt;=&lt;/span&gt; (x1 &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; x2) &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; sconcat (x3 &lt;span class="op"&gt;:|&lt;/span&gt; xs)&lt;/span&gt;
&lt;span id="cb10-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb10-4" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb10-5" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;merges ::&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;Root&lt;/span&gt; k v] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span id="cb10-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb10-6" tabindex="-1"&gt;&lt;/a&gt;merges &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; sconcat &lt;span class="op"&gt;.&lt;/span&gt; nonEmpty&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The pattern of this two-level merge is what gives the pairing heap
its excellent performance.&lt;/p&gt;
&lt;p&gt;The &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Heap&lt;/span&gt;&lt;/code&gt; type
derives its monoid instance from the monoid instance on &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Maybe&lt;/span&gt;&lt;/code&gt; (&lt;code class="sourceCode haskell"&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Semigroup&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Monoid&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; a)&lt;/code&gt;),
so we can implement &lt;code class="sourceCode haskell"&gt;insert&lt;/code&gt; like
so:&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="https://doisinkidney.com/rss.xml#cb11-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;insert ::&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb11-2" tabindex="-1"&gt;&lt;/a&gt;insert k v hp &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; (&lt;span class="dt"&gt;Root&lt;/span&gt; k v []) &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; hp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And &lt;code class="sourceCode haskell"&gt;popMin&lt;/code&gt; is also relatively
simple:&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="https://doisinkidney.com/rss.xml#cb12-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;delay ::&lt;/span&gt; &lt;span class="dt"&gt;Semigroup&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb12-2" tabindex="-1"&gt;&lt;/a&gt;delay by &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; (\(&lt;span class="dt"&gt;Root&lt;/span&gt; k v xs) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; (by &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; k) v xs)&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb12-3" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb12-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;popMin ::&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k v &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (v,&lt;span class="dt"&gt;Heap&lt;/span&gt; k v)&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb12-5" tabindex="-1"&gt;&lt;/a&gt;popMin &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; (\(&lt;span class="dt"&gt;Root&lt;/span&gt; k v xs) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (v, k &lt;span class="ot"&gt;`delay`&lt;/span&gt; merges xs))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that we &lt;code class="sourceCode haskell"&gt;delay&lt;/code&gt; the rest
of the heap, because all of its entries need to be offset by the weight
of the previous root node. Thankfully, because weâ€™re only storing the
differences, we can â€œmodifyâ€� every weight by just increasing the weight
of the root, making this an
&amp;lt;semantics&amp;gt;ğ�’ª(1)&amp;lt;annotation encoding="application/x-tex"&amp;gt;\mathcal{O}(1)&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
operation.&lt;/p&gt;
&lt;p&gt;Finally, we can implement heap sort like so:&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="https://doisinkidney.com/rss.xml#cb13-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sortOn ::&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb13-2" tabindex="-1"&gt;&lt;/a&gt;sortOn k &lt;span class="ot"&gt;=&lt;/span&gt; unfoldr popMin &lt;span class="op"&gt;.&lt;/span&gt; foldl' (\xs x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; insert (k x) x xs) &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And it does indeed work:&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="https://doisinkidney.com/rss.xml#cb14-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; sortOn &lt;span class="dt"&gt;Sum&lt;/span&gt; [&lt;span class="dv"&gt;3&lt;/span&gt;,&lt;span class="dv"&gt;4&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb14-2" tabindex="-1"&gt;&lt;/a&gt;[&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;span class="dv"&gt;3&lt;/span&gt;,&lt;span class="dv"&gt;4&lt;/span&gt;,&lt;span class="dv"&gt;5&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is a trace of the output:&lt;/p&gt;
&lt;details&gt;

Trace

&lt;pre class="text"&gt;&lt;code&gt;Input           Heap:
list:

[3,4,2,5,1]


[4,2,5,1]       3


[2,5,1]         3â”€1


[5,1]           2â”€1â”€1


[1]              â”Œ3
                2â”¤
                 â””1â”€1


[]                 â”Œ3
                1â”€1â”¤
                   â””1â”€1


Output          Heap:
list:

[]                 â”Œ3
                1â”€1â”¤
                   â””1â”€1


[1]              â”Œ3
                2â”¤
                 â””1â”€1


[1,2]            â”Œ2
                3â”¤
                 â””1


[1,2,3]         4â”€1


[1,2,3,4]       5


[1,2,3,4,5]&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;While the heap implementation presented here is pretty efficient,
note that we could significantly improve its performance with a few
optimisations: first, we could unpack all of the constructors, using a
custom list definition in &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Root&lt;/span&gt;&lt;/code&gt; instead
of Haskellâ€™s built-in lists; second, in &lt;code class="sourceCode haskell"&gt;foldl'&lt;/code&gt; we could avoid the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Maybe&lt;/span&gt;&lt;/code&gt; wrapper
by building a non-empty heap. There are probably more small
optimisations available as well.&lt;/p&gt;
&lt;h1 id="retrieving-a-normal-heap"&gt;Retrieving a Normal Heap&lt;/h1&gt;
&lt;p&gt;A problem with the definition of &lt;code class="sourceCode haskell"&gt;sortOn&lt;/code&gt; above is that it requires a
&lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Monus&lt;/span&gt;&lt;/code&gt;
instance on the keys, but it only really needs &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Ord&lt;/span&gt;&lt;/code&gt;. It seems
that by switching to the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Monus&lt;/span&gt;&lt;/code&gt;-powered
heap we have lost some generality.&lt;/p&gt;
&lt;p&gt;Luckily, there are two monuses we can use to solve this problem:&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="https://doisinkidney.com/rss.xml#cb16-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; (&lt;span class="dt"&gt;Max&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb16-2" tabindex="-1"&gt;&lt;/a&gt;  x âˆ¸ y &lt;span class="ot"&gt;=&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb16-3" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb16-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; (&lt;span class="dt"&gt;Last&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb16-5" tabindex="-1"&gt;&lt;/a&gt;  x âˆ¸ y &lt;span class="ot"&gt;=&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Max&lt;/span&gt;&lt;/code&gt; semigroup
uses the &lt;code class="sourceCode haskell"&gt;&lt;span class="fu"&gt;max&lt;/span&gt;&lt;/code&gt; operation,
and the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Last&lt;/span&gt;&lt;/code&gt; semigroup
returns its second operand.&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="https://doisinkidney.com/rss.xml#cb17-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; a &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Semigroup&lt;/span&gt; (&lt;span class="dt"&gt;Max&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb17-2" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; (&lt;span class="fu"&gt;max&lt;/span&gt; x y)&lt;/span&gt;
&lt;span id="cb17-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb17-3" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb17-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb17-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Semigroup&lt;/span&gt; (&lt;span class="dt"&gt;Last&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb17-5" tabindex="-1"&gt;&lt;/a&gt;  x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; y &lt;span class="ot"&gt;=&lt;/span&gt; y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Monus&lt;/span&gt;&lt;/code&gt;
instances here might seem degenerate, they do actually satisfy the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Monus&lt;/span&gt;&lt;/code&gt; laws as
given above.&lt;/p&gt;
&lt;details&gt;

&lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Max&lt;/span&gt;&lt;/code&gt; and
&lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Last&lt;/span&gt;&lt;/code&gt;
Monus laws

&lt;p&gt;Max:&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="https://doisinkidney.com/rss.xml#cb18-1" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (y âˆ¸ x) &lt;span class="ot"&gt;=&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-2" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Max&lt;/span&gt; y âˆ¸ &lt;span class="dt"&gt;Max&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-3" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; (&lt;span class="fu"&gt;max&lt;/span&gt; x y) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-5" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;max&lt;/span&gt; x y &lt;span class="ot"&gt;=&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-6" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-7" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-8" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb18-9"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-9" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Max&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; (&lt;span class="fu"&gt;max&lt;/span&gt; z x) &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Max&lt;/span&gt; (&lt;span class="fu"&gt;max&lt;/span&gt; z y)&lt;/span&gt;
&lt;span id="cb18-10"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb18-10" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;max&lt;/span&gt; z x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="fu"&gt;max&lt;/span&gt; z y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Last:&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-1" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (y âˆ¸ x) &lt;span class="ot"&gt;=&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-2" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (&lt;span class="dt"&gt;Last&lt;/span&gt; y âˆ¸ &lt;span class="dt"&gt;Last&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-3" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-5" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-6" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb19-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-7" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; z &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span id="cb19-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb19-8" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y &lt;span class="op"&gt;==&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; x &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dt"&gt;Last&lt;/span&gt; y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;Either &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Max&lt;/span&gt;&lt;/code&gt; or &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Last&lt;/span&gt;&lt;/code&gt; will
work; semantically, thereâ€™s no real difference. &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Last&lt;/span&gt;&lt;/code&gt; avoids
some comparisons, so we can use that:&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb20-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;sortOn' ::&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; k) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb20-2" tabindex="-1"&gt;&lt;/a&gt;sortOn' k &lt;span class="ot"&gt;=&lt;/span&gt; sortOn (&lt;span class="dt"&gt;Last&lt;/span&gt; &lt;span class="op"&gt;.&lt;/span&gt; k)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="phases-as-a-pairing-heap"&gt;Phases as a Pairing Heap&lt;/h1&gt;
&lt;p&gt;The &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Phases&lt;/span&gt;&lt;/code&gt;
applicative &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-easterly_functions_2019"&gt;Easterly
2019&lt;/a&gt;)&lt;/span&gt; is an &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Applicative&lt;/span&gt;&lt;/code&gt;
transformer that allows reordering of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Applicative&lt;/span&gt;&lt;/code&gt;
effects in an easy-to-use, high-level way. The interface looks like
this:&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb21-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;phase     ::&lt;/span&gt; &lt;span class="dt"&gt;Natural&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Phases&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb21-2" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;runPhases ::&lt;/span&gt; &lt;span class="dt"&gt;Applicative&lt;/span&gt; f &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Phases&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb21-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb21-3" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb21-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Applicative&lt;/span&gt; f &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Applicative&lt;/span&gt; (&lt;span class="dt"&gt;Phases&lt;/span&gt; f)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can use it like this:&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;phased ::&lt;/span&gt; &lt;span class="dt"&gt;IO&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-2" tabindex="-1"&gt;&lt;/a&gt;phased &lt;span class="ot"&gt;=&lt;/span&gt; runPhases &lt;span class="op"&gt;$&lt;/span&gt; &lt;span class="fu"&gt;sequenceA&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-3" tabindex="-1"&gt;&lt;/a&gt;  [ phase &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; emit &lt;span class="ch"&gt;'a'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-4" tabindex="-1"&gt;&lt;/a&gt;  , phase &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; emit &lt;span class="ch"&gt;'b'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-5" tabindex="-1"&gt;&lt;/a&gt;  , phase &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; emit &lt;span class="ch"&gt;'c'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-6" tabindex="-1"&gt;&lt;/a&gt;  , phase &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; emit &lt;span class="ch"&gt;'d'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-7" tabindex="-1"&gt;&lt;/a&gt;  , phase &lt;span class="dv"&gt;3&lt;/span&gt; &lt;span class="op"&gt;$&lt;/span&gt; emit &lt;span class="ch"&gt;'e'&lt;/span&gt; ]&lt;/span&gt;
&lt;span id="cb22-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-8" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt; emit c &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;putChar&lt;/span&gt; c &lt;span class="op"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;return&lt;/span&gt; c&lt;/span&gt;
&lt;span id="cb22-9"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-9" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb22-10"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-10" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; phased&lt;/span&gt;
&lt;span id="cb22-11"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-11" tabindex="-1"&gt;&lt;/a&gt;cbdae&lt;/span&gt;
&lt;span id="cb22-12"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb22-12" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="st"&gt;"abcde"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above computation performs the &lt;em&gt;effects&lt;/em&gt; in the order
dictated by their phases (this is why the characters are printed out in
the order &lt;code class="sourceCode haskell"&gt;cbdae&lt;/code&gt;), but the pure
value (the returned string) has its order unaffected.&lt;/p&gt;
&lt;p&gt;I have written about this type &lt;a href="https://doisinkidney.com/2019-05-28-linear-phases.html"&gt;before&lt;/a&gt;, and in a handful of
papers &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;; &lt;a href="https://doisinkidney.com/rss.xml#ref-gibbons_breadthfirst_2022"&gt;Gibbons et
al. 2022&lt;/a&gt;; &lt;a href="https://doisinkidney.com/rss.xml#ref-gibbons_phases_2023"&gt;Gibbons et al. 2023&lt;/a&gt;)&lt;/span&gt;, but more recently
&lt;span class="citation"&gt;BlÃ¶ndal (&lt;a href="https://doisinkidney.com/rss.xml#ref-blondal_generalized_2025"&gt;2025a&lt;/a&gt;)&lt;/span&gt; started looking into trying to
use the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Phases&lt;/span&gt;&lt;/code&gt; pattern
with arbitrary ordered keys &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-visscher_phases_2025"&gt;Visscher 2025&lt;/a&gt;;
&lt;a href="https://doisinkidney.com/rss.xml#ref-blondal_phases_2025"&gt;BlÃ¶ndal
2025b&lt;/a&gt;)&lt;/span&gt;. There are a lot of different directions you can go
from the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Phases&lt;/span&gt;&lt;/code&gt; type;
what interested me most immediately was the idea of implementing the
type efficiently using standard data-structure representations. If our
core goal here is to order some values according to a key, then that is
clearly a problem that a heap should solve: enter the free applicative
pairing heap.&lt;/p&gt;
&lt;p&gt;Here is the typeâ€™s definition:&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k f a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-2" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Pure&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-3" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Root&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-4" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-5" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-6" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Nil&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f ()&lt;/span&gt;
&lt;span id="cb23-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb23-7" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;App&lt;/span&gt;&lt;span class="ot"&gt; ::&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f z &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f (x,y,z)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We have had to change a few aspects of the original pairing heap, but
the overall structure remains. The entries in this heap are now
effectful computations: the &lt;code class="sourceCode haskell"&gt;f&lt;/code&gt;s.
The data structure also contains some scaffolding to reconstruct the
pure values â€œinsideâ€� each effect when we actually run the heap.&lt;/p&gt;
&lt;p&gt;The root-level structure is the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Heap&lt;/span&gt;&lt;/code&gt;: this can
either be &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Pure&lt;/span&gt;&lt;/code&gt;
(corresponding to an empty heap: notice that, though this constructor
has some contents (the &lt;code class="sourceCode haskell"&gt;a&lt;/code&gt;), it is
still regarded as â€œemptyâ€� because it contains no effects (&lt;code class="sourceCode haskell"&gt;f&lt;/code&gt;)); or a &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Root&lt;/span&gt;&lt;/code&gt;, which is
a singleton value, paired with the list of sub-heaps represented by the
&lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Heaps&lt;/span&gt;&lt;/code&gt;
type. Weâ€™re using the usual Yoneda-ish trick here to allow the top-level
data type to be parametric and a &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Functor&lt;/span&gt;&lt;/code&gt;, by
storing the function &lt;code class="sourceCode haskell"&gt;x &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; y &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Heaps&lt;/span&gt;&lt;/code&gt; type
then plays the role of &lt;code class="sourceCode haskell"&gt;[&lt;span class="dt"&gt;Root&lt;/span&gt; k v]&lt;/code&gt; in
the previous pairing heap implementation; here, we have inlined all of
the constructors so that we can get all of the types to line up.
Remember, this is a heap of &lt;em&gt;effects&lt;/em&gt;, not of pure values: the
pure values need to be able to be reconstructed to one single top-level
&lt;code class="sourceCode haskell"&gt;a&lt;/code&gt; when we run the heap at the
end.&lt;/p&gt;
&lt;p&gt;Merging two heaps happens in the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Applicative&lt;/span&gt;&lt;/code&gt;
instance itself:&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Functor&lt;/span&gt; (&lt;span class="dt"&gt;Heap&lt;/span&gt; k f) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-2" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;fmap&lt;/span&gt; f (&lt;span class="dt"&gt;Pure&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Pure&lt;/span&gt; (f x)&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-3" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;fmap&lt;/span&gt; f (&lt;span class="dt"&gt;Root&lt;/span&gt; k c x xs) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; k (\a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f (c a b)) x xs&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-4" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-5" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Applicative&lt;/span&gt; (&lt;span class="dt"&gt;Heap&lt;/span&gt; k f) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-6" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Pure&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-7" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Pure&lt;/span&gt; f &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; xs &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; f xs&lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-8" tabindex="-1"&gt;&lt;/a&gt;  xs &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Pure&lt;/span&gt; f &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; (&lt;span class="op"&gt;$&lt;/span&gt; f) xs&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-9" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-10"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-10" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Root&lt;/span&gt; xk xc xs xss &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; yk yc ys yss&lt;/span&gt;
&lt;span id="cb24-11"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-11" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;|&lt;/span&gt; xk &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; yk  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; xk (\a (b,c,d) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; xc a d (yc b c)) xs (&lt;span class="dt"&gt;App&lt;/span&gt; (yk âˆ¸ xk) ys yss xss)&lt;/span&gt;
&lt;span id="cb24-12"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb24-12" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; yk (\a (b,c,d) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; xc b c (yc a d)) ys (&lt;span class="dt"&gt;App&lt;/span&gt; (xk âˆ¸ yk) xs xss yss)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To actually run the heap we will use the following two functions:&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;merges ::&lt;/span&gt; (&lt;span class="dt"&gt;Monus&lt;/span&gt; k, &lt;span class="dt"&gt;Applicative&lt;/span&gt; f) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heaps&lt;/span&gt; k f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-2" tabindex="-1"&gt;&lt;/a&gt;merges &lt;span class="dt"&gt;Nil&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Pure&lt;/span&gt; ()&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-3" tabindex="-1"&gt;&lt;/a&gt;merges (&lt;span class="dt"&gt;App&lt;/span&gt; k1 e1 t1 &lt;span class="dt"&gt;Nil&lt;/span&gt;) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; k1 (,,()) e1 t1&lt;/span&gt;
&lt;span id="cb25-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-4" tabindex="-1"&gt;&lt;/a&gt;merges (&lt;span class="dt"&gt;App&lt;/span&gt; k1 e1 t1 (&lt;span class="dt"&gt;App&lt;/span&gt; k2 e2 t2 xs)) &lt;span class="ot"&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb25-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-5" tabindex="-1"&gt;&lt;/a&gt;   (&lt;span class="dt"&gt;Root&lt;/span&gt; k1 (\a b cd es &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (a,b, cd es)) e1 t1 &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; k2 (,,) e2 t2) &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; merges xs&lt;/span&gt;
&lt;span id="cb25-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-6" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-7" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;runHeap ::&lt;/span&gt; (&lt;span class="dt"&gt;Monus&lt;/span&gt; k, &lt;span class="dt"&gt;Applicative&lt;/span&gt; f) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb25-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-8" tabindex="-1"&gt;&lt;/a&gt;runHeap (&lt;span class="dt"&gt;Pure&lt;/span&gt; x) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt; x&lt;/span&gt;
&lt;span id="cb25-9"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb25-9" tabindex="-1"&gt;&lt;/a&gt;runHeap (&lt;span class="dt"&gt;Root&lt;/span&gt; _ c x xs) &lt;span class="ot"&gt;=&lt;/span&gt; liftA2 c x (runHeap (merges xs))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can lift a computation into &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Phases&lt;/span&gt;&lt;/code&gt; like
so:&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb26-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;phase ::&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb26-2" tabindex="-1"&gt;&lt;/a&gt;phase k xs &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; k &lt;span class="fu"&gt;const&lt;/span&gt; xs &lt;span class="dt"&gt;Nil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="stabilising-phases"&gt;Stabilising Phases&lt;/h1&gt;
&lt;p&gt;Thereâ€™s a problem. A heap sort based on a pairing heap isnâ€™t
&lt;em&gt;stable&lt;/em&gt;. That means that the order of effects here can vary for
two effects in the same phase. If we look back to the example with the
strings we saw above, that means that outputs like &lt;code class="sourceCode haskell"&gt;cdbea&lt;/code&gt; would be possible (in actual
fact, we donâ€™t get any reordering in this particular example, but thatâ€™s
just an accident of the way the applicative operators are associated
under the hood).&lt;/p&gt;
&lt;p&gt;This is problematic because we would expect effects in the same phase
to behave as if they were normal applicative effects, sequenced
according to their syntactic order. It also means that the applicative
transformer breaks the applicative laws, because effects might be
reordered according to the association of the applicative operators,
which should lawfully be associative.&lt;/p&gt;
&lt;p&gt;To make the sort stable, we could layer the heap effect with some
state effect that would tag each effect with its order. However, that
would hurt efficiency and composability: it would force us to linearise
the whole heap sort procedure, where currently different branches of the
tree can compute completely independently of each other. The solution
comes in the form of another monus: the key monus.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb27-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Key&lt;/span&gt; k &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;k &lt;span class="op"&gt;:*&lt;/span&gt; &lt;span class="ot"&gt;{-# UNPACK #-}&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;&lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="kw"&gt;deriving&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt;, &lt;span class="dt"&gt;Ord&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Key&lt;/span&gt; k&lt;/code&gt; is some
ordered key &lt;code class="sourceCode haskell"&gt;k&lt;/code&gt; coupled with an
&lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/code&gt; that
represents the offset between the original position and the current
position of the key. In this way, when two keys compare as equal, we can
cascade on to compare their original positions, thereby maintaining
their original order when there is ambiguity caused by a key collision.
However, in contrast to the approach of walking over the data once and
tagging it all with positions, this approach keeps the location
information completely local: we never need to know that some key is in
the
&amp;lt;semantics&amp;gt;n&amp;lt;annotation encoding="application/x-tex"&amp;gt;n&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;th
position in the original sequence, only that it has moved
&amp;lt;semantics&amp;gt;n&amp;lt;annotation encoding="application/x-tex"&amp;gt;n&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
steps from its original position.&lt;/p&gt;
&lt;p&gt;The instances are as follows:&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb28-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Semigroup&lt;/span&gt; (&lt;span class="dt"&gt;Key&lt;/span&gt; k) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb28-2" tabindex="-1"&gt;&lt;/a&gt;  (xk &lt;span class="op"&gt;:*&lt;/span&gt; xi) &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (yk &lt;span class="op"&gt;:*&lt;/span&gt; yi) &lt;span class="ot"&gt;=&lt;/span&gt; yk &lt;span class="op"&gt;:*&lt;/span&gt; (xi &lt;span class="op"&gt;+&lt;/span&gt; yi)&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb28-3" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb28-4" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; (&lt;span class="dt"&gt;Key&lt;/span&gt; k) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb28-5" tabindex="-1"&gt;&lt;/a&gt;  (xk &lt;span class="op"&gt;:*&lt;/span&gt; xi) âˆ¸ (yk &lt;span class="op"&gt;:*&lt;/span&gt; yi) &lt;span class="ot"&gt;=&lt;/span&gt; xk &lt;span class="op"&gt;:*&lt;/span&gt; (xi &lt;span class="op"&gt;-&lt;/span&gt; yi)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This instance is basically a combination of the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Last&lt;/span&gt;&lt;/code&gt; semigroup
and the
&amp;lt;semantics&amp;gt;(â„¤,+,0)&amp;lt;annotation encoding="application/x-tex"&amp;gt;(\mathbb{Z}, +, 0)&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
group. We could make a slightly more generalised version of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Key&lt;/span&gt;&lt;/code&gt; that is
the combination of any monus and
&amp;lt;semantics&amp;gt;â„¤&amp;lt;annotation encoding="application/x-tex"&amp;gt;\mathbb{Z}&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;,
but since Iâ€™m only going to be using this type for simple sorting-like
algorithms I will leave that generalisation for another time.&lt;/p&gt;
&lt;p&gt;The stable heap type is as follows:&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb29-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;data&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; k f a&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb29-2" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; {&lt;span class="ot"&gt; size ::&lt;/span&gt; &lt;span class="ot"&gt;{-# UNPACK #-}&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;&lt;span class="dt"&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb29-3" tabindex="-1"&gt;&lt;/a&gt;           ,&lt;span class="ot"&gt; heap ::&lt;/span&gt; &lt;span class="op"&gt;!&lt;/span&gt;(&lt;span class="dt"&gt;Heap&lt;/span&gt; (&lt;span class="dt"&gt;Key&lt;/span&gt; k) f a) }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We need to track the size of the heap so that we can supply the
right-hand operand with their offsets. Because weâ€™re storing
differences, we can add an offset to every entry in a heap in
&amp;lt;semantics&amp;gt;ğ�’ª(1)&amp;lt;annotation encoding="application/x-tex"&amp;gt;\mathcal{O}(1)&amp;lt;/annotation&amp;gt;&amp;lt;/semantics&amp;gt;
time by simply adding to the root:&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb30-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;delayKey ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; (&lt;span class="dt"&gt;Key&lt;/span&gt; k) f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Heap&lt;/span&gt; (&lt;span class="dt"&gt;Key&lt;/span&gt; k) f a&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb30-2" tabindex="-1"&gt;&lt;/a&gt;delayKey _ hp&lt;span class="op"&gt;@&lt;/span&gt;(&lt;span class="dt"&gt;Pure&lt;/span&gt; _) &lt;span class="ot"&gt;=&lt;/span&gt; hp&lt;/span&gt;
&lt;span id="cb30-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb30-3" tabindex="-1"&gt;&lt;/a&gt;delayKey n (&lt;span class="dt"&gt;Root&lt;/span&gt; (k &lt;span class="op"&gt;:*&lt;/span&gt; m) c x xs) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Root&lt;/span&gt; (k &lt;span class="op"&gt;:*&lt;/span&gt; (n &lt;span class="op"&gt;+&lt;/span&gt; m)) c x xs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, using this we can implement the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Applicative&lt;/span&gt;&lt;/code&gt;
instance and the rest of the interface:&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Applicative&lt;/span&gt; (&lt;span class="dt"&gt;Stable&lt;/span&gt; k f) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-2" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="fu"&gt;pure&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;pure&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-3" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="dt"&gt;Stable&lt;/span&gt; n xs &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; m ys &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; (n&lt;span class="op"&gt;+&lt;/span&gt;m) (xs &lt;span class="op"&gt;&amp;lt;*&amp;gt;&lt;/span&gt; delayKey n ys)&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-4" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-5" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;runStable ::&lt;/span&gt; (&lt;span class="dt"&gt;Applicative&lt;/span&gt; f, &lt;span class="dt"&gt;Ord&lt;/span&gt; k) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; k f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-6" tabindex="-1"&gt;&lt;/a&gt;runStable &lt;span class="ot"&gt;=&lt;/span&gt; runHeap &lt;span class="op"&gt;.&lt;/span&gt; heap&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-7" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-8" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;stable ::&lt;/span&gt; &lt;span class="dt"&gt;Ord&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; k &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; k f a&lt;/span&gt;
&lt;span id="cb31-9"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb31-9" tabindex="-1"&gt;&lt;/a&gt;stable k fa &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Stable&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; (phase (k &lt;span class="op"&gt;:*&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;) fa)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a pure, optimally efficient implementation of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Phases&lt;/span&gt;&lt;/code&gt; ordered
by an arbitrary total-ordered key.&lt;/p&gt;
&lt;h1 id="local-computation-in-a-monadic-heap"&gt;Local Computation in a
Monadic Heap&lt;/h1&gt;
&lt;p&gt;In &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;)&lt;/span&gt;,
I developed a monadic heap based on the free monad transformer.&lt;/p&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb32-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;newtype&lt;/span&gt; &lt;span class="dt"&gt;Search&lt;/span&gt; k a &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Search&lt;/span&gt; {&lt;span class="ot"&gt; runSearch ::&lt;/span&gt; [&lt;span class="dt"&gt;Either&lt;/span&gt; a (k, &lt;span class="dt"&gt;Search&lt;/span&gt; k a)] }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This type is equivalent to the &lt;a href="https://hackage.haskell.org/package/free-5.2/docs/Control-Monad-Trans-Free.html#t:FreeT"&gt;free
monad transformer&lt;/a&gt; over the list monad and &lt;code class="sourceCode haskell"&gt;(,) k&lt;/code&gt; functor (i.e.Â the writer
monad).&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb33-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Search&lt;/span&gt; k a â‰… &lt;span class="dt"&gt;FreeT&lt;/span&gt; ((,) k) [] a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the paper &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;)&lt;/span&gt; we extended the type to become a
full monad transformer, replacing lists with &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;ListT&lt;/span&gt;&lt;/code&gt;. This
let us order the effects according to the weight &lt;code class="sourceCode haskell"&gt;k&lt;/code&gt;; however, for this example we only
need the simplified type, which lets us order the values according to
&lt;code class="sourceCode haskell"&gt;k&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Search&lt;/span&gt;&lt;/code&gt; type
follows the structure of a pairing heap (although not as closely as the
version above). However, this type is interesting because
&lt;em&gt;semantically&lt;/em&gt; it needs the weights to be stored as differences,
rather than absolute weights. As a free monad transformer, the &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Search&lt;/span&gt;&lt;/code&gt; type
layers effects on top of each other; we can later interpret those layers
by collapsing them together using the monadic &lt;code class="sourceCode haskell"&gt;join&lt;/code&gt;. In the case of &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Search&lt;/span&gt;&lt;/code&gt;, those
layers are drawn from the list monad and the &lt;code class="sourceCode haskell"&gt;(,) k&lt;/code&gt; functor (writer monad). That
means that if we have some heap representing the tree from above:&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb34-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="dt"&gt;Search&lt;/span&gt; [ &lt;span class="dt"&gt;Right&lt;/span&gt; (a, &lt;span class="dt"&gt;Search&lt;/span&gt; [ &lt;span class="dt"&gt;Right&lt;/span&gt; (b, &lt;span class="dt"&gt;Search&lt;/span&gt; [ &lt;span class="dt"&gt;Right&lt;/span&gt; (d, &lt;span class="dt"&gt;Search&lt;/span&gt; [&lt;span class="dt"&gt;Left&lt;/span&gt; x])&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb34-2" tabindex="-1"&gt;&lt;/a&gt;                                             , &lt;span class="dt"&gt;Right&lt;/span&gt; (e, &lt;span class="dt"&gt;Search&lt;/span&gt; [&lt;span class="dt"&gt;Left&lt;/span&gt; y])])&lt;/span&gt;
&lt;span id="cb34-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb34-3" tabindex="-1"&gt;&lt;/a&gt;                          , &lt;span class="dt"&gt;Right&lt;/span&gt; (c, &lt;span class="dt"&gt;Search&lt;/span&gt; [&lt;span class="dt"&gt;Left&lt;/span&gt; z])])]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we collapse this computation down to the leaves, the weights we
will get are the following:&lt;/p&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb35-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb35-1" tabindex="-1"&gt;&lt;/a&gt;[(a &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; b &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; d, x), (a &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; b &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; e, y), (a &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; c, z)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, if we want the weights to line up properly, we need to store the
differences.&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-1" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;mergeS ::&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; [(k, &lt;span class="dt"&gt;Search&lt;/span&gt; k a)] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; (k, &lt;span class="dt"&gt;Search&lt;/span&gt; k a)&lt;/span&gt;
&lt;span id="cb36-2"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-2" tabindex="-1"&gt;&lt;/a&gt;mergeS [] &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Nothing&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-3"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-3" tabindex="-1"&gt;&lt;/a&gt;mergeS (x&lt;span class="op"&gt;:&lt;/span&gt;xs) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; (mergeS' x xs)&lt;/span&gt;
&lt;span id="cb36-4"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-4" tabindex="-1"&gt;&lt;/a&gt;  &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-5"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-5" tabindex="-1"&gt;&lt;/a&gt;    mergeS' x1 [] &lt;span class="ot"&gt;=&lt;/span&gt; x1&lt;/span&gt;
&lt;span id="cb36-6"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-6" tabindex="-1"&gt;&lt;/a&gt;    mergeS' x1 [x2] &lt;span class="ot"&gt;=&lt;/span&gt; x1 &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; x2&lt;/span&gt;
&lt;span id="cb36-7"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-7" tabindex="-1"&gt;&lt;/a&gt;    mergeS' x1 (x2&lt;span class="op"&gt;:&lt;/span&gt;x3&lt;span class="op"&gt;:&lt;/span&gt;xs) &lt;span class="ot"&gt;=&lt;/span&gt; (x1 &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; x2) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; mergeS' x3 xs&lt;/span&gt;
&lt;span id="cb36-8"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-8" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-9"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-9" tabindex="-1"&gt;&lt;/a&gt;    (xw, &lt;span class="dt"&gt;Search&lt;/span&gt; xs) &lt;span class="op"&gt;&amp;lt;+&amp;gt;&lt;/span&gt; (yw, &lt;span class="dt"&gt;Search&lt;/span&gt; ys)&lt;/span&gt;
&lt;span id="cb36-10"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-10" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; xw &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; yw  &lt;span class="ot"&gt;=&lt;/span&gt; (xw, &lt;span class="dt"&gt;Search&lt;/span&gt; (&lt;span class="dt"&gt;Right&lt;/span&gt; (yw âˆ¸ xw, &lt;span class="dt"&gt;Search&lt;/span&gt; ys) &lt;span class="op"&gt;:&lt;/span&gt; xs))&lt;/span&gt;
&lt;span id="cb36-11"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-11" tabindex="-1"&gt;&lt;/a&gt;      &lt;span class="op"&gt;|&lt;/span&gt; &lt;span class="fu"&gt;otherwise&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; (yw, &lt;span class="dt"&gt;Search&lt;/span&gt; (&lt;span class="dt"&gt;Right&lt;/span&gt; (xw âˆ¸ yw, &lt;span class="dt"&gt;Search&lt;/span&gt; xs) &lt;span class="op"&gt;:&lt;/span&gt; ys))&lt;/span&gt;
&lt;span id="cb36-12"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-12" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-13"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-13" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;popMins ::&lt;/span&gt; &lt;span class="dt"&gt;Monus&lt;/span&gt; k &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Search&lt;/span&gt; k a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; ([a], &lt;span class="dt"&gt;Maybe&lt;/span&gt; (k, &lt;span class="dt"&gt;Search&lt;/span&gt; k a))&lt;/span&gt;
&lt;span id="cb36-14"&gt;&lt;a href="https://doisinkidney.com/rss.xml#cb36-14" tabindex="-1"&gt;&lt;/a&gt;popMins &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; mergeS &lt;span class="op"&gt;.&lt;/span&gt; partitionEithers &lt;span class="op"&gt;.&lt;/span&gt; runSearch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1 id="conclusion"&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The technique of â€œdonâ€™t store the absolute value, store the
differenceâ€� seems to be generally quite useful; I think that monuses are
a handy algebra to keep in mind whenever that technique looks like it
might be needed. The &lt;code class="sourceCode haskell"&gt;&lt;span class="dt"&gt;Key&lt;/span&gt;&lt;/code&gt; monus
above is closely related to the factorial numbers, and the trick I used
in &lt;a href="https://doisinkidney.com/2019-03-24-permutations-by-sorting.html"&gt;this&lt;/a&gt; post.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 class="unnumbered" id="references"&gt;References&lt;/h2&gt;
&lt;div class="references csl-bib-body hanging-indent" id="refs"&gt;
&lt;div class="csl-entry" id="ref-amer_equationally_1984"&gt;
Amer, K. 1984. &lt;span&gt;â€œEquationally complete classes of commutative
monoids with monus.â€�&lt;/span&gt; &lt;em&gt;algebra universalis&lt;/em&gt; 18 (1)
(February): 129â€“131. doi:&lt;a href="https://doi.org/10.1007/BF01182254"&gt;10.1007/BF01182254&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-blondal_generalized_2025"&gt;
BlÃ¶ndal, Baldur. 2025a. &lt;span&gt;â€œGeneralized multi-phase
compiler/concurrency.â€�&lt;/span&gt; &lt;em&gt;reddit&lt;/em&gt;. &lt;a href="https://www.reddit.com/r/haskell/comments/1m25fw8/generalized_multiphase_compilerconcurrency/"&gt;https://www.reddit.com/r/haskell/comments/1m25fw8/generalized_multiphase_compilerconcurrency/&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-blondal_phases_2025"&gt;
â€”â€”â€”. 2025b. &lt;span&gt;â€œPhases using &lt;span&gt;Vault&lt;/span&gt;.â€�&lt;/span&gt;
&lt;em&gt;reddit&lt;/em&gt;. &lt;a href="https://www.reddit.com/r/haskell/comments/1msvwzd/phases_using_vault/"&gt;https://www.reddit.com/r/haskell/comments/1msvwzd/phases_using_vault/&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-easterly_functions_2019"&gt;
Easterly, Noah. 2019. &lt;span&gt;â€œFunctions and newtype wrappers for
traversing &lt;span&gt;Trees&lt;/span&gt;: Rampion/tree-traversals.â€�&lt;/span&gt; &lt;a href="https://github.com/rampion/tree-traversals"&gt;https://github.com/rampion/tree-traversals&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-fredman_pairing_1986"&gt;
Fredman, Michael L., Robert Sedgewick, Daniel D. Sleator, and Robert E.
Tarjan. 1986. &lt;span&gt;â€œThe pairing heap: &lt;span&gt;A&lt;/span&gt; new form of
self-adjusting heap.â€�&lt;/span&gt; &lt;em&gt;Algorithmica&lt;/em&gt; 1 (1-4) (January):
111â€“129. doi:&lt;a href="https://doi.org/10.1007/BF01840439"&gt;10.1007/BF01840439&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-gibbons_breadthfirst_2022"&gt;
Gibbons, Jeremy, Donnacha OisÃ­n Kidney, Tom Schrijvers, and Nicolas Wu.
2022. &lt;span&gt;â€œBreadth-&lt;span&gt;First Traversal&lt;/span&gt;
viaÂ &lt;span&gt;Staging&lt;/span&gt;.â€�&lt;/span&gt; In &lt;em&gt;Mathematics of &lt;span&gt;Program
Construction&lt;/span&gt;&lt;/em&gt;, ed by. Ekaterina Komendantskaya, 1â€“33. Cham:
Springer International Publishing. doi:&lt;a href="https://doi.org/10.1007/978-3-031-16912-0_1"&gt;10.1007/978-3-031-16912-0_1&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-gibbons_phases_2023"&gt;
â€”â€”â€”. 2023. &lt;span&gt;â€œPhases in &lt;span&gt;Software Architecture&lt;/span&gt;.â€�&lt;/span&gt;
In &lt;em&gt;Proceedings of the 1st &lt;span&gt;ACM SIGPLAN International
Workshop&lt;/span&gt; on &lt;span&gt;Functional Software Architecture&lt;/span&gt;&lt;/em&gt;,
29â€“33. &lt;span&gt;FUNARCH&lt;/span&gt; 2023. New York, NY, USA: Association for
Computing Machinery. doi:&lt;a href="https://doi.org/10.1145/3609025.3609479"&gt;10.1145/3609025.3609479&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-kidney_algebras_2021"&gt;
Kidney, Donnacha OisÃ­n, and Nicolas Wu. 2021. &lt;span&gt;â€œAlgebras for
weighted search.â€�&lt;/span&gt; &lt;em&gt;Proceedings of the ACM on Programming
Languages&lt;/em&gt; 5 (ICFP) (August): 72:1â€“72:30. doi:&lt;a href="https://doi.org/10.1145/3473577"&gt;10.1145/3473577&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-kidney_formalising_2025"&gt;
â€”â€”â€”. 2025. &lt;span&gt;â€œFormalising &lt;span&gt;Graph Algorithms&lt;/span&gt; with
&lt;span&gt;Coinduction&lt;/span&gt;.â€�&lt;/span&gt; &lt;em&gt;Proc. ACM Program. Lang.&lt;/em&gt; 9
(POPL) (January): 56:1657â€“56:1686. doi:&lt;a href="https://doi.org/10.1145/3704892"&gt;10.1145/3704892&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-larkin_backtobasics_2013"&gt;
Larkin, Daniel H., Siddhartha Sen, and Robert E. Tarjan. 2013. &lt;span&gt;â€œA
&lt;span class="nocase"&gt;Back-to-Basics Empirical Study&lt;/span&gt; of
&lt;span&gt;Priority Queues&lt;/span&gt;.â€�&lt;/span&gt; In &lt;em&gt;2014
&lt;span&gt;Proceedings&lt;/span&gt; of the &lt;span&gt;Meeting&lt;/span&gt; on &lt;span&gt;Algorithm
Engineering&lt;/span&gt; and &lt;span&gt;Experiments&lt;/span&gt;
(&lt;span&gt;ALENEX&lt;/span&gt;)&lt;/em&gt;, 61â€“72. Proceedings. &lt;span&gt;Society for
Industrial and Applied Mathematics&lt;/span&gt;. doi:&lt;a href="https://doi.org/10.1137/1.9781611973198.7"&gt;10.1137/1.9781611973198.7&lt;/a&gt;.
&lt;/div&gt;
&lt;div class="csl-entry" id="ref-visscher_phases_2025"&gt;
Visscher, Sjoerd. 2025. &lt;span&gt;â€œPhases with any &lt;span&gt;Ord&lt;/span&gt; key
type.â€�&lt;/span&gt; &lt;a href="https://gist.github.com/sjoerdvisscher/bf282a050f0681e2f737908e254c4061"&gt;https://gist.github.com/sjoerdvisscher/bf282a050f0681e2f737908e254c4061&lt;/a&gt;.
&lt;/div&gt;
&lt;/div&gt;
&lt;section class="footnotes footnotes-end-of-document" id="footnotes"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn1"&gt;&lt;p&gt;Note that there are many related structures that all
fall under the umbrella notion of â€œmonusâ€�; the structure that I am
defining here is the same structure I worked with in &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;)&lt;/span&gt;
and &lt;span class="citation"&gt;(&lt;a href="https://doisinkidney.com/rss.xml#ref-kidney_formalising_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;.&lt;a class="footnote-back" href="https://doisinkidney.com/rss.xml#fnref1"&gt;â†©ï¸�&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><pubDate>Tue, 03 Mar 2026 00:00:00 +0000</pubDate><ns0:encoded xmlns:ns0="http://purl.org/rss/1.0/modules/content/">&lt;div id="content" morss_own_score="5.6217672413793105" morss_score="241.47769153177657"&gt;
&lt;h2&gt;Monuses and Heaps&lt;/h2&gt;
&lt;div&gt;
    Posted on March  3, 2026
&lt;/div&gt;


&lt;div&gt;
    
        Tags: &lt;a title="All pages tagged 'Haskell'." href="https://doisinkidney.com/tags/Haskell.html"&gt;Haskell&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;This post is about a simple algebraic structure that I have found
useful for algorithms that involve searching or sorting based on some
ordered weight. I used it a bit in a pair of papers on graph search
&lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;; &lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-kidney_formalising_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;, and more recently I used it to
implement a version of the &lt;code&gt;&lt;span&gt;Phases&lt;/span&gt;&lt;/code&gt; type
&lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-easterly_functions_2019"&gt;Easterly
2019&lt;/a&gt;)&lt;/span&gt; that supported arbitrary keys, inspired by some work by
Blöndal &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-blondal_generalized_2025"&gt;2025a&lt;/a&gt;; &lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-blondal_phases_2025"&gt;2025b&lt;/a&gt;)&lt;/span&gt;
and &lt;span&gt;Visscher
(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-visscher_phases_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;The algebraic structure in question is a &lt;em&gt;monus&lt;/em&gt;, which is a
kind of monoid that supports a partial subtraction operation (that
subtraction operation, denoted by the symbol ∸, is itself often called a
“monus”). However, before giving the full definition of the structure,
let me first try to motivate its use. The context here is heap-based
algorithms. For the purposes of this post, a heap is a tree that obeys
the “heap property”; i.e. every node in the tree has some “weight”
attached to it, and every parent node has a weight less than or equal to
the weight of each of its children. So, for a tree like the
following:&lt;/p&gt;

&lt;p&gt;The heap property is satisfied when
&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;b&lt;/mi&gt;&lt;annotation&gt;a \leq b&lt;/annotation&gt;,
&lt;mi&gt;a&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;c&lt;/mi&gt;&lt;annotation&gt;a \leq c&lt;/annotation&gt;,
&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;annotation&gt;b \leq d&lt;/annotation&gt;,
and
&lt;mi&gt;b&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;annotation&gt;b \leq e&lt;/annotation&gt;.&lt;/p&gt;
&lt;p&gt;Usually, we also want our heap structure to have an operation like
&lt;code&gt;&lt;span&gt;popMin ::&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Maybe&lt;/span&gt; (v, &lt;span&gt;Heap&lt;/span&gt; k v)&lt;/code&gt;
that returns the least-weight value in the heap paired with the rest of
the heap. If this operation is efficient, we can use the heap to
efficiently implement sorting algorithms, graph search, etc. In fact,
let me give the whole basic interface for a heap here:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;popMin ::&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Maybe&lt;/span&gt; (v, &lt;span&gt;Heap&lt;/span&gt; k v)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;insert ::&lt;/span&gt; k &lt;span&gt;-&amp;gt;&lt;/span&gt; v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empty  ::&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using these functions it’s not hard to see how we can implement a
sorting algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;sortOn ::&lt;/span&gt; (a &lt;span&gt;-&amp;gt;&lt;/span&gt; k) &lt;span&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; unfoldr popMin &lt;span&gt;.&lt;/span&gt; &lt;span&gt;foldr&lt;/span&gt; (\x &lt;span&gt;-&amp;gt;&lt;/span&gt; insert (k x) x) empty&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The monus becomes relevant when the weight involved is some kind of
&lt;em&gt;monoid&lt;/em&gt;. This is quite a common situation: if we were using the
heap for graph search (least-cost paths or something), we would expect
the weight to correspond to path costs, and we would expect that we can
add the costs of paths in a kind of monoidal way. Furthermore, we would
probably expect the monoidal operations to relate to the order in some
coherent way. A monus &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-amer_equationally_1984"&gt;Amer
1984&lt;/a&gt;)&lt;/span&gt; is an ordered monoid where the order itself can be
defined &lt;em&gt;in terms&lt;/em&gt; of the monoidal operations&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#fn1"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;⇔&lt;/mo&gt;&lt;mo&gt;∃&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mi&gt;.&lt;/mi&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;•&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;annotation&gt; x \leq y \iff \exists z. \; y = x \bullet z &lt;/annotation&gt;&lt;/p&gt;
&lt;p&gt;I read this definition as saying
“&lt;mi&gt;x&lt;/mi&gt;&lt;annotation&gt;x&lt;/annotation&gt;
is less than
&lt;mi&gt;y&lt;/mi&gt;&lt;annotation&gt;y&lt;/annotation&gt;
iff there is some
&lt;mi&gt;z&lt;/mi&gt;&lt;annotation&gt;z&lt;/annotation&gt;
that &lt;em&gt;fits between&lt;/em&gt;
&lt;mi&gt;x&lt;/mi&gt;&lt;annotation&gt;x&lt;/annotation&gt;
and
&lt;mi&gt;y&lt;/mi&gt;&lt;annotation&gt;y&lt;/annotation&gt;”.
In other words, the &lt;em&gt;gap&lt;/em&gt; between
&lt;mi&gt;x&lt;/mi&gt;&lt;annotation&gt;x&lt;/annotation&gt;
and
&lt;mi&gt;y&lt;/mi&gt;&lt;annotation&gt;y&lt;/annotation&gt;
has to exist, and it is equal to
&lt;mi&gt;z&lt;/mi&gt;&lt;annotation&gt;z&lt;/annotation&gt;.&lt;/p&gt;
&lt;p&gt;Notice that this order definition won’t work for groups like
&lt;mo&gt;(&lt;/mo&gt;&lt;mi&gt;ℤ&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;annotation&gt;(\mathbb{Z},+,0)&lt;/annotation&gt;.
For a group, we can &lt;em&gt;always&lt;/em&gt; find some
&lt;mi&gt;z&lt;/mi&gt;&lt;annotation&gt;z&lt;/annotation&gt;
that will fit the existential (specifically,
&lt;mi&gt;z&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo&gt;(&lt;/mo&gt;&lt;mi&gt;−&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;mo&gt;•&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation&gt;z = (- x) \bullet y&lt;/annotation&gt;).
Monuses, then, tend to be positive monoids: in fact, many monuses are
the positive cones of some group
(&lt;mo&gt;(&lt;/mo&gt;&lt;mi&gt;ℕ&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;annotation&gt;(\mathbb{N},+,0)&lt;/annotation&gt;
is the positive cone of
&lt;mo&gt;(&lt;/mo&gt;&lt;mi&gt;ℤ&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;annotation&gt;(\mathbb{Z},+,0)&lt;/annotation&gt;).&lt;/p&gt;
&lt;p&gt;We can derive a lot of useful properties from this basic structure.
For example, if the order above is total, then we can derive the binary
subtraction operator mentioned above:&lt;/p&gt;
&lt;p&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;∸&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo&gt;{&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext&gt;if &lt;/mtext&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mtext&gt; and &lt;/mtext&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;•&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mtext&gt;otherwise.&lt;/mtext&gt;&lt;annotation&gt; x ∸ y =
\begin{cases}
z, &amp;amp; \text{if } y \leq x \text{ and } x = y \bullet z  \\
0, &amp;amp; \text{otherwise.}
\end{cases}
&lt;/annotation&gt;&lt;/p&gt;
&lt;p&gt;If we require the underlying monoid to be commutative, and we further
require the derived order to be total and antisymmetric, we get the
particular flavour of monus I worked with in a pair of papers on graph
search &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;; &lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-kidney_formalising_2025"&gt;2025&lt;/a&gt;)&lt;/span&gt;. In this post I will actually be
working with a weakened form of the algebra that I will define
shortly.&lt;/p&gt;
&lt;p&gt;Getting back to our heap from above, with this new order defined, we
can see that the heap property actually tells us something about the
makeup of the weights in the tree. Instead of every child just having a
weight equal to some arbitrary quantity, the heap property tells us that
each child weight has to be made up of the combination of its parent’s
weight and some difference.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;

&lt;span&gt;&lt;span&gt;=&lt;/span&gt;  a┤       └b•(e∸b)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This observation gives us an opportunity for a different
representation: instead of storing the full weight at each node, we
could instead just store the difference.&lt;/p&gt;

&lt;p&gt;Just in terms of data structure design, I prefer this version: if we
wanted to write down a type of heaps using the previous design, we would
first define the type of trees, and then separately write a predicate
corresponding to the heap property. With this design, it is impossible
to write down a tree that &lt;em&gt;doesn’t&lt;/em&gt; satisfy the heap
property.&lt;/p&gt;
&lt;p&gt;More practically, though, using this algebraic structure when working
with heaps enables some optimisations that might be difficult to
implement otherwise. The strength of this representation is that it
allows for efficient relative and global computation: now, if we wanted
to add some quantity to every weight in the tree, we can do it just by
adding the weight to the root node.&lt;/p&gt;
&lt;h1&gt;Monuses in Haskell&lt;/h1&gt;
&lt;p&gt;To see some examples of how to use this pattern, let’s first write a
class for Haskell monuses:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;class&lt;/span&gt; (&lt;span&gt;Semigroup&lt;/span&gt; a, &lt;span&gt;Ord&lt;/span&gt; a) &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; a &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ::&lt;/span&gt; a &lt;span&gt;-&amp;gt;&lt;/span&gt; a &lt;span&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll notice that we’re requiring semigroup here, not monoid. That’s
because one of the nice uses of this pattern actually works with a
weakening of the usual monus algebra; this weakening only requires
semigroup, and the following two laws.&lt;/p&gt;
&lt;p&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;⟹&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;•&lt;/mo&gt;&lt;mo&gt;(&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;∸&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;mo&gt;⟹&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo&gt;•&lt;/mo&gt;&lt;mi&gt;x&lt;/mi&gt;&lt;mo&gt;≤&lt;/mo&gt;&lt;mi&gt;z&lt;/mi&gt;&lt;mo&gt;•&lt;/mo&gt;&lt;mi&gt;y&lt;/mi&gt;&lt;annotation&gt; x \leq y \implies x \bullet (y ∸ x) = y
\quad \quad \quad \quad \quad
x \leq y \implies z \bullet x \leq z \bullet y &lt;/annotation&gt;&lt;/p&gt;
&lt;p&gt;A straightforward monus instance is the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; (&lt;span&gt;Num&lt;/span&gt; a, &lt;span&gt;Ord&lt;/span&gt; a) &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; (&lt;span&gt;Sum&lt;/span&gt; a) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; (&lt;span&gt;-&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Pairing Heaps in Haskell&lt;/h1&gt;
&lt;p&gt;Next, let’s look at a simple heap implementation. I will always go
for pairing heaps &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-fredman_pairing_1986"&gt;Fredman et al. 1986&lt;/a&gt;)&lt;/span&gt; in Haskell; they
are extremely simple to implement, and (as long as you don’t have
significant persistence requirements) their performance seems to be the
best of the available pointer-based heaps &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-larkin_backtobasics_2013"&gt;Larkin, Sen,
and Tarjan 2013&lt;/a&gt;)&lt;/span&gt;. Here is the type definition:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;data&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; k v &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;k v [&lt;span&gt;Root&lt;/span&gt; k v]&lt;/span&gt;
&lt;span&gt;&lt;span&gt;type&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Maybe&lt;/span&gt; (&lt;span&gt;Root&lt;/span&gt; k v)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;&lt;span&gt;Root&lt;/span&gt;&lt;/code&gt; is a
non-empty pairing heap; the &lt;code&gt;&lt;span&gt;Heap&lt;/span&gt;&lt;/code&gt; type
represents possibly-empty heaps. The key function to implement is the
merging of two heaps; we can accomplish this as an implementation of the
semigroup &lt;code&gt;&lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Semigroup&lt;/span&gt; (&lt;span&gt;Root&lt;/span&gt; k v) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Root&lt;/span&gt; xk xv xs &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; yk yv ys&lt;/span&gt;
&lt;span&gt;&lt;span&gt;|&lt;/span&gt; xk &lt;span&gt;&amp;lt;=&lt;/span&gt; yk  &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; xk xv (&lt;span&gt;Root&lt;/span&gt; (yk ∸ xk) yv ys &lt;span&gt;:&lt;/span&gt; xs)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;|&lt;/span&gt; &lt;span&gt;otherwise&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; yk yv (&lt;span&gt;Root&lt;/span&gt; (xk ∸ yk) xv xs &lt;span&gt;:&lt;/span&gt; ys)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only difference between this and a normal pairing heap merge is
the use of &lt;code&gt;∸&lt;/code&gt; in the key of the
child node (&lt;code&gt;yk ∸ xk&lt;/code&gt; and &lt;code&gt;xk ∸ yk&lt;/code&gt;). This difference ensures that
each child only holds the difference of the weight between itself and
its parent.&lt;/p&gt;
&lt;p&gt;It’s worth working out why the weakened monus laws above are all we
need in order to maintain the heap property on this structure.&lt;/p&gt;
&lt;p&gt;The rest of the methods are implemented the same as their
implementations on a normal pairing heap. First, we have the pairing
merge of a list of heaps, here given as an implementation of the
semigroup method &lt;code&gt;sconcat&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;:|&lt;/span&gt; []) &lt;span&gt;=&lt;/span&gt; x1&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:|&lt;/span&gt; [x2]) &lt;span&gt;=&lt;/span&gt; x1 &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; x2&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:|&lt;/span&gt; x2 &lt;span&gt;:&lt;/span&gt; x3 &lt;span&gt;:&lt;/span&gt; xs) &lt;span&gt;=&lt;/span&gt; (x1 &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; x2) &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; sconcat (x3 &lt;span&gt;:|&lt;/span&gt; xs)&lt;/span&gt;

&lt;span&gt;&lt;span&gt;merges ::&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; [&lt;span&gt;Root&lt;/span&gt; k v] &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;fmap&lt;/span&gt; sconcat &lt;span&gt;.&lt;/span&gt; nonEmpty&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The pattern of this two-level merge is what gives the pairing heap
its excellent performance.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span&gt;Heap&lt;/span&gt;&lt;/code&gt; type
derives its monoid instance from the monoid instance on &lt;code&gt;&lt;span&gt;Maybe&lt;/span&gt;&lt;/code&gt; (&lt;code&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Semigroup&lt;/span&gt; a &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Monoid&lt;/span&gt; (&lt;span&gt;Maybe&lt;/span&gt; a)&lt;/code&gt;),
so we can implement &lt;code&gt;insert&lt;/code&gt; like
so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;insert ::&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; k &lt;span&gt;-&amp;gt;&lt;/span&gt; v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;Just&lt;/span&gt; (&lt;span&gt;Root&lt;/span&gt; k v []) &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; hp&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;code&gt;popMin&lt;/code&gt; is also relatively
simple:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;delay ::&lt;/span&gt; &lt;span&gt;Semigroup&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; k &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;fmap&lt;/span&gt; (\(&lt;span&gt;Root&lt;/span&gt; k v xs) &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; (by &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; k) v xs)&lt;/span&gt;

&lt;span&gt;&lt;span&gt;popMin ::&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k v &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Maybe&lt;/span&gt; (v,&lt;span&gt;Heap&lt;/span&gt; k v)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;fmap&lt;/span&gt; (\(&lt;span&gt;Root&lt;/span&gt; k v xs) &lt;span&gt;-&amp;gt;&lt;/span&gt; (v, k &lt;span&gt;`delay`&lt;/span&gt; merges xs))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that we &lt;code&gt;delay&lt;/code&gt; the rest
of the heap, because all of its entries need to be offset by the weight
of the previous root node. Thankfully, because we’re only storing the
differences, we can “modify” every weight by just increasing the weight
of the root, making this an
&lt;mi&gt;𝒪&lt;/mi&gt;&lt;mo&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;annotation&gt;\mathcal{O}(1)&lt;/annotation&gt;
operation.&lt;/p&gt;
&lt;p&gt;Finally, we can implement heap sort like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;sortOn ::&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; (a &lt;span&gt;-&amp;gt;&lt;/span&gt; k) &lt;span&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; unfoldr popMin &lt;span&gt;.&lt;/span&gt; foldl' (\xs x &lt;span&gt;-&amp;gt;&lt;/span&gt; insert (k x) x xs) &lt;span&gt;Nothing&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it does indeed work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; sortOn &lt;span&gt;Sum&lt;/span&gt; [&lt;span&gt;3&lt;/span&gt;,&lt;span&gt;4&lt;/span&gt;,&lt;span&gt;2&lt;/span&gt;,&lt;span&gt;5&lt;/span&gt;,&lt;span&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span&gt;&lt;span&gt;1&lt;/span&gt;,&lt;span&gt;2&lt;/span&gt;,&lt;span&gt;3&lt;/span&gt;,&lt;span&gt;4&lt;/span&gt;,&lt;span&gt;5&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here is a trace of the output:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
Trace
&lt;/summary&gt;
&lt;pre&gt;&lt;code&gt;Input           Heap:
list:

[3,4,2,5,1]


[4,2,5,1]       3


[2,5,1]         3─1


[5,1]           2─1─1


[1]              ┌3
                2┤
                 └1─1


[]                 ┌3
                1─1┤
                   └1─1


Output          Heap:
list:

[]                 ┌3
                1─1┤
                   └1─1


[1]              ┌3
                2┤
                 └1─1


[1,2]            ┌2
                3┤
                 └1


[1,2,3]         4─1


[1,2,3,4]       5


[1,2,3,4,5]&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;While the heap implementation presented here is pretty efficient,
note that we could significantly improve its performance with a few
optimisations: first, we could unpack all of the constructors, using a
custom list definition in &lt;code&gt;&lt;span&gt;Root&lt;/span&gt;&lt;/code&gt; instead
of Haskell’s built-in lists; second, in &lt;code&gt;foldl'&lt;/code&gt; we could avoid the &lt;code&gt;&lt;span&gt;Maybe&lt;/span&gt;&lt;/code&gt; wrapper
by building a non-empty heap. There are probably more small
optimisations available as well.&lt;/p&gt;
&lt;h1&gt;Retrieving a Normal Heap&lt;/h1&gt;
&lt;p&gt;A problem with the definition of &lt;code&gt;sortOn&lt;/code&gt; above is that it requires a
&lt;code&gt;&lt;span&gt;Monus&lt;/span&gt;&lt;/code&gt;
instance on the keys, but it only really needs &lt;code&gt;&lt;span&gt;Ord&lt;/span&gt;&lt;/code&gt;. It seems
that by switching to the &lt;code&gt;&lt;span&gt;Monus&lt;/span&gt;&lt;/code&gt;-powered
heap we have lost some generality.&lt;/p&gt;
&lt;p&gt;Luckily, there are two monuses we can use to solve this problem:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; a &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; (&lt;span&gt;Max&lt;/span&gt; a) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; x&lt;/span&gt;

&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; a &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; (&lt;span&gt;Last&lt;/span&gt; a) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&lt;span&gt;Max&lt;/span&gt;&lt;/code&gt; semigroup
uses the &lt;code&gt;&lt;span&gt;max&lt;/span&gt;&lt;/code&gt; operation,
and the &lt;code&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/code&gt; semigroup
returns its second operand.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; a &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Semigroup&lt;/span&gt; (&lt;span&gt;Max&lt;/span&gt; a) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; (&lt;span&gt;max&lt;/span&gt; x y)&lt;/span&gt;

&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Semigroup&lt;/span&gt; (&lt;span&gt;Last&lt;/span&gt; a) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; y &lt;span&gt;=&lt;/span&gt; y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While the &lt;code&gt;&lt;span&gt;Monus&lt;/span&gt;&lt;/code&gt;
instances here might seem degenerate, they do actually satisfy the &lt;code&gt;&lt;span&gt;Monus&lt;/span&gt;&lt;/code&gt; laws as
given above.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;
&lt;code&gt;&lt;span&gt;Max&lt;/span&gt;&lt;/code&gt; and
&lt;code&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/code&gt;
Monus laws
&lt;/summary&gt;
&lt;p&gt;Max:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; (y ∸ x) &lt;span&gt;=&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; (&lt;span&gt;Max&lt;/span&gt; y ∸ &lt;span&gt;Max&lt;/span&gt; x) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; (&lt;span&gt;max&lt;/span&gt; x y) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;max&lt;/span&gt; x y &lt;span&gt;=&lt;/span&gt; y&lt;/span&gt;

&lt;span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Max&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; (&lt;span&gt;max&lt;/span&gt; z x) &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Max&lt;/span&gt; (&lt;span&gt;max&lt;/span&gt; z y)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;max&lt;/span&gt; z x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;max&lt;/span&gt; z y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Last:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; (y ∸ x) &lt;span&gt;=&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; (&lt;span&gt;Last&lt;/span&gt; y ∸ &lt;span&gt;Last&lt;/span&gt; x) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y&lt;/span&gt;

&lt;span&gt;&lt;span&gt;&amp;lt;=&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; z &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y &lt;span&gt;==&amp;gt;&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; x &lt;span&gt;&amp;lt;=&lt;/span&gt; &lt;span&gt;Last&lt;/span&gt; y&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/details&gt;
&lt;p&gt;Either &lt;code&gt;&lt;span&gt;Max&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/code&gt; will
work; semantically, there’s no real difference. &lt;code&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/code&gt; avoids
some comparisons, so we can use that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;sortOn' ::&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; (a &lt;span&gt;-&amp;gt;&lt;/span&gt; k) &lt;span&gt;-&amp;gt;&lt;/span&gt; [a] &lt;span&gt;-&amp;gt;&lt;/span&gt; [a]&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; sortOn (&lt;span&gt;Last&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; k)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Phases as a Pairing Heap&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;&lt;span&gt;Phases&lt;/span&gt;&lt;/code&gt;
applicative &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-easterly_functions_2019"&gt;Easterly
2019&lt;/a&gt;)&lt;/span&gt; is an &lt;code&gt;&lt;span&gt;Applicative&lt;/span&gt;&lt;/code&gt;
transformer that allows reordering of &lt;code&gt;&lt;span&gt;Applicative&lt;/span&gt;&lt;/code&gt;
effects in an easy-to-use, high-level way. The interface looks like
this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;phase     ::&lt;/span&gt; &lt;span&gt;Natural&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; f a &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Phases&lt;/span&gt; f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;runPhases ::&lt;/span&gt; &lt;span&gt;Applicative&lt;/span&gt; f &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Phases&lt;/span&gt; f a &lt;span&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;

&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Applicative&lt;/span&gt; f &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Applicative&lt;/span&gt; (&lt;span&gt;Phases&lt;/span&gt; f)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can use it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;phased ::&lt;/span&gt; &lt;span&gt;IO&lt;/span&gt; &lt;span&gt;String&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; runPhases &lt;span&gt;$&lt;/span&gt; &lt;span&gt;sequenceA&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;3&lt;/span&gt; &lt;span&gt;$&lt;/span&gt; emit &lt;span&gt;'a'&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;2&lt;/span&gt; &lt;span&gt;$&lt;/span&gt; emit &lt;span&gt;'b'&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;1&lt;/span&gt; &lt;span&gt;$&lt;/span&gt; emit &lt;span&gt;'c'&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;2&lt;/span&gt; &lt;span&gt;$&lt;/span&gt; emit &lt;span&gt;'d'&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;3&lt;/span&gt; &lt;span&gt;$&lt;/span&gt; emit &lt;span&gt;'e'&lt;/span&gt; ]&lt;/span&gt;
&lt;span&gt;&lt;span&gt;where&lt;/span&gt; emit c &lt;span&gt;=&lt;/span&gt; &lt;span&gt;putChar&lt;/span&gt; c &lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span&gt;return&lt;/span&gt; c&lt;/span&gt;

&lt;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; phased&lt;/span&gt;

&lt;span&gt;"abcde"&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above computation performs the &lt;em&gt;effects&lt;/em&gt; in the order
dictated by their phases (this is why the characters are printed out in
the order &lt;code&gt;cbdae&lt;/code&gt;), but the pure
value (the returned string) has its order unaffected.&lt;/p&gt;
&lt;p&gt;I have written about this type &lt;a href="https://doisinkidney.com/posts/2019-05-28-linear-phases.html"&gt;before&lt;/a&gt;, and in a handful of
papers &lt;span&gt;Blöndal (&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-blondal_generalized_2025"&gt;2025a&lt;/a&gt;)&lt;/span&gt; started looking into trying to
use the &lt;code&gt;&lt;span&gt;Phases&lt;/span&gt;&lt;/code&gt; pattern
with arbitrary ordered keys &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-visscher_phases_2025"&gt;Visscher 2025&lt;/a&gt;;
&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-blondal_phases_2025"&gt;Blöndal
2025b&lt;/a&gt;)&lt;/span&gt;. There are a lot of different directions you can go
from the &lt;code&gt;&lt;span&gt;Phases&lt;/span&gt;&lt;/code&gt; type;
what interested me most immediately was the idea of implementing the
type efficiently using standard data-structure representations. If our
core goal here is to order some values according to a key, then that is
clearly a problem that a heap should solve: enter the free applicative
pairing heap.&lt;/p&gt;
&lt;p&gt;Here is the type’s definition:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;data&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k f a &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Pure&lt;/span&gt;&lt;span&gt; ::&lt;/span&gt; a &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Root&lt;/span&gt;&lt;span&gt; ::&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;k &lt;span&gt;-&amp;gt;&lt;/span&gt; (x &lt;span&gt;-&amp;gt;&lt;/span&gt; y &lt;span&gt;-&amp;gt;&lt;/span&gt; a) &lt;span&gt;-&amp;gt;&lt;/span&gt; f x &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f y &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;

&lt;span&gt;&lt;span&gt;data&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f a &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Nil&lt;/span&gt;&lt;span&gt; ::&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f ()&lt;/span&gt;
&lt;span&gt;&lt;span&gt;App&lt;/span&gt;&lt;span&gt; ::&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;k &lt;span&gt;-&amp;gt;&lt;/span&gt; f x &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f y &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f z &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f (x,y,z)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have had to change a few aspects of the original pairing heap, but
the overall structure remains. The entries in this heap are now
effectful computations: the &lt;code&gt;f&lt;/code&gt;s.
The data structure also contains some scaffolding to reconstruct the
pure values “inside” each effect when we actually run the heap.&lt;/p&gt;
&lt;p&gt;The root-level structure is the &lt;code&gt;&lt;span&gt;Heap&lt;/span&gt;&lt;/code&gt;: this can
either be &lt;code&gt;&lt;span&gt;Pure&lt;/span&gt;&lt;/code&gt;
(corresponding to an empty heap: notice that, though this constructor
has some contents (the &lt;code&gt;a&lt;/code&gt;), it is
still regarded as “empty” because it contains no effects (&lt;code&gt;f&lt;/code&gt;)); or a &lt;code&gt;&lt;span&gt;Root&lt;/span&gt;&lt;/code&gt;, which is
a singleton value, paired with the list of sub-heaps represented by the
&lt;code&gt;&lt;span&gt;Heaps&lt;/span&gt;&lt;/code&gt;
type. We’re using the usual Yoneda-ish trick here to allow the top-level
data type to be parametric and a &lt;code&gt;&lt;span&gt;Functor&lt;/span&gt;&lt;/code&gt;, by
storing the function &lt;code&gt;x &lt;span&gt;-&amp;gt;&lt;/span&gt; y &lt;span&gt;-&amp;gt;&lt;/span&gt; a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;&lt;span&gt;Heaps&lt;/span&gt;&lt;/code&gt; type
then plays the role of &lt;code&gt;[&lt;span&gt;Root&lt;/span&gt; k v]&lt;/code&gt; in
the previous pairing heap implementation; here, we have inlined all of
the constructors so that we can get all of the types to line up.
Remember, this is a heap of &lt;em&gt;effects&lt;/em&gt;, not of pure values: the
pure values need to be able to be reconstructed to one single top-level
&lt;code&gt;a&lt;/code&gt; when we run the heap at the
end.&lt;/p&gt;
&lt;p&gt;Merging two heaps happens in the &lt;code&gt;&lt;span&gt;Applicative&lt;/span&gt;&lt;/code&gt;
instance itself:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Functor&lt;/span&gt; (&lt;span&gt;Heap&lt;/span&gt; k f) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;fmap&lt;/span&gt; f (&lt;span&gt;Pure&lt;/span&gt; x) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Pure&lt;/span&gt; (f x)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;fmap&lt;/span&gt; f (&lt;span&gt;Root&lt;/span&gt; k c x xs) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; k (\a b &lt;span&gt;-&amp;gt;&lt;/span&gt; f (c a b)) x xs&lt;/span&gt;

&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Applicative&lt;/span&gt; (&lt;span&gt;Heap&lt;/span&gt; k f) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;pure&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Pure&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Pure&lt;/span&gt; f &lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; xs &lt;span&gt;=&lt;/span&gt; &lt;span&gt;fmap&lt;/span&gt; f xs&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span&gt;Pure&lt;/span&gt; f &lt;span&gt;=&lt;/span&gt; &lt;span&gt;fmap&lt;/span&gt; (&lt;span&gt;$&lt;/span&gt; f) xs&lt;/span&gt;

&lt;span&gt;&lt;span&gt;Root&lt;/span&gt; xk xc xs xss &lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; yk yc ys yss&lt;/span&gt;
&lt;span&gt;&lt;span&gt;|&lt;/span&gt; xk &lt;span&gt;&amp;lt;=&lt;/span&gt; yk  &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; xk (\a (b,c,d) &lt;span&gt;-&amp;gt;&lt;/span&gt; xc a d (yc b c)) xs (&lt;span&gt;App&lt;/span&gt; (yk ∸ xk) ys yss xss)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;|&lt;/span&gt; &lt;span&gt;otherwise&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; yk (\a (b,c,d) &lt;span&gt;-&amp;gt;&lt;/span&gt; xc b c (yc a d)) ys (&lt;span&gt;App&lt;/span&gt; (xk ∸ yk) xs xss yss)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To actually run the heap we will use the following two functions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;merges ::&lt;/span&gt; (&lt;span&gt;Monus&lt;/span&gt; k, &lt;span&gt;Applicative&lt;/span&gt; f) &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Heaps&lt;/span&gt; k f a &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Nil&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Pure&lt;/span&gt; ()&lt;/span&gt;
&lt;span&gt;&lt;span&gt;App&lt;/span&gt; k1 e1 t1 &lt;span&gt;Nil&lt;/span&gt;) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; k1 (,,()) e1 t1&lt;/span&gt;
&lt;span&gt;&lt;span&gt;App&lt;/span&gt; k1 e1 t1 (&lt;span&gt;App&lt;/span&gt; k2 e2 t2 xs)) &lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Root&lt;/span&gt; k1 (\a b cd es &lt;span&gt;-&amp;gt;&lt;/span&gt; (a,b, cd es)) e1 t1 &lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; k2 (,,) e2 t2) &lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; merges xs&lt;/span&gt;

&lt;span&gt;&lt;span&gt;runHeap ::&lt;/span&gt; (&lt;span&gt;Monus&lt;/span&gt; k, &lt;span&gt;Applicative&lt;/span&gt; f) &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k f a &lt;span&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Pure&lt;/span&gt; x) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;pure&lt;/span&gt; x&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Root&lt;/span&gt; _ c x xs) &lt;span&gt;=&lt;/span&gt; liftA2 c x (runHeap (merges xs))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we can lift a computation into &lt;code&gt;&lt;span&gt;Phases&lt;/span&gt;&lt;/code&gt; like
so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;phase ::&lt;/span&gt; k &lt;span&gt;-&amp;gt;&lt;/span&gt; f a &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; k f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; k &lt;span&gt;const&lt;/span&gt; xs &lt;span&gt;Nil&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Stabilising Phases&lt;/h1&gt;
&lt;p&gt;There’s a problem. A heap sort based on a pairing heap isn’t
&lt;em&gt;stable&lt;/em&gt;. That means that the order of effects here can vary for
two effects in the same phase. If we look back to the example with the
strings we saw above, that means that outputs like &lt;code&gt;cdbea&lt;/code&gt; would be possible (in actual
fact, we don’t get any reordering in this particular example, but that’s
just an accident of the way the applicative operators are associated
under the hood).&lt;/p&gt;
&lt;p&gt;This is problematic because we would expect effects in the same phase
to behave as if they were normal applicative effects, sequenced
according to their syntactic order. It also means that the applicative
transformer breaks the applicative laws, because effects might be
reordered according to the association of the applicative operators,
which should lawfully be associative.&lt;/p&gt;
&lt;p&gt;To make the sort stable, we could layer the heap effect with some
state effect that would tag each effect with its order. However, that
would hurt efficiency and composability: it would force us to linearise
the whole heap sort procedure, where currently different branches of the
tree can compute completely independently of each other. The solution
comes in the form of another monus: the key monus.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;data&lt;/span&gt; &lt;span&gt;Key&lt;/span&gt; k &lt;span&gt;=&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;k &lt;span&gt;:*&lt;/span&gt; &lt;span&gt;{-# UNPACK #-}&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;&lt;span&gt;Int&lt;/span&gt; &lt;span&gt;deriving&lt;/span&gt; (&lt;span&gt;Eq&lt;/span&gt;, &lt;span&gt;Ord&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A &lt;code&gt;&lt;span&gt;Key&lt;/span&gt; k&lt;/code&gt; is some
ordered key &lt;code&gt;k&lt;/code&gt; coupled with an
&lt;code&gt;&lt;span&gt;Int&lt;/span&gt;&lt;/code&gt; that
represents the offset between the original position and the current
position of the key. In this way, when two keys compare as equal, we can
cascade on to compare their original positions, thereby maintaining
their original order when there is ambiguity caused by a key collision.
However, in contrast to the approach of walking over the data once and
tagging it all with positions, this approach keeps the location
information completely local: we never need to know that some key is in
the
&lt;mi&gt;n&lt;/mi&gt;&lt;annotation&gt;n&lt;/annotation&gt;th
position in the original sequence, only that it has moved
&lt;mi&gt;n&lt;/mi&gt;&lt;annotation&gt;n&lt;/annotation&gt;
steps from its original position.&lt;/p&gt;
&lt;p&gt;The instances are as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Semigroup&lt;/span&gt; (&lt;span&gt;Key&lt;/span&gt; k) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:*&lt;/span&gt; xi) &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; (yk &lt;span&gt;:*&lt;/span&gt; yi) &lt;span&gt;=&lt;/span&gt; yk &lt;span&gt;:*&lt;/span&gt; (xi &lt;span&gt;+&lt;/span&gt; yi)&lt;/span&gt;

&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; (&lt;span&gt;Key&lt;/span&gt; k) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:*&lt;/span&gt; xi) ∸ (yk &lt;span&gt;:*&lt;/span&gt; yi) &lt;span&gt;=&lt;/span&gt; xk &lt;span&gt;:*&lt;/span&gt; (xi &lt;span&gt;-&lt;/span&gt; yi)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This instance is basically a combination of the &lt;code&gt;&lt;span&gt;Last&lt;/span&gt;&lt;/code&gt; semigroup
and the
&lt;mo&gt;(&lt;/mo&gt;&lt;mi&gt;ℤ&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mi&gt;+&lt;/mi&gt;&lt;mo&gt;,&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;annotation&gt;(\mathbb{Z}, +, 0)&lt;/annotation&gt;
group. We could make a slightly more generalised version of &lt;code&gt;&lt;span&gt;Key&lt;/span&gt;&lt;/code&gt; that is
the combination of any monus and
&lt;mi&gt;ℤ&lt;/mi&gt;&lt;annotation&gt;\mathbb{Z}&lt;/annotation&gt;,
but since I’m only going to be using this type for simple sorting-like
algorithms I will leave that generalisation for another time.&lt;/p&gt;
&lt;p&gt;The stable heap type is as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;data&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; k f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; {&lt;span&gt; size ::&lt;/span&gt; &lt;span&gt;{-# UNPACK #-}&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;&lt;span&gt;Int&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; heap ::&lt;/span&gt; &lt;span&gt;!&lt;/span&gt;(&lt;span&gt;Heap&lt;/span&gt; (&lt;span&gt;Key&lt;/span&gt; k) f a) }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to track the size of the heap so that we can supply the
right-hand operand with their offsets. Because we’re storing
differences, we can add an offset to every entry in a heap in
&lt;mi&gt;𝒪&lt;/mi&gt;&lt;mo&gt;(&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo&gt;)&lt;/mo&gt;&lt;annotation&gt;\mathcal{O}(1)&lt;/annotation&gt;
time by simply adding to the root:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;delayKey ::&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; (&lt;span&gt;Key&lt;/span&gt; k) f a &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Heap&lt;/span&gt; (&lt;span&gt;Key&lt;/span&gt; k) f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;(&lt;span&gt;Pure&lt;/span&gt; _) &lt;span&gt;=&lt;/span&gt; hp&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Root&lt;/span&gt; (k &lt;span&gt;:*&lt;/span&gt; m) c x xs) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Root&lt;/span&gt; (k &lt;span&gt;:*&lt;/span&gt; (n &lt;span&gt;+&lt;/span&gt; m)) c x xs&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, using this we can implement the &lt;code&gt;&lt;span&gt;Applicative&lt;/span&gt;&lt;/code&gt;
instance and the rest of the interface:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;instance&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Applicative&lt;/span&gt; (&lt;span&gt;Stable&lt;/span&gt; k f) &lt;span&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;pure&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; &lt;span&gt;0&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;pure&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Stable&lt;/span&gt; n xs &lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; m ys &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; (n&lt;span&gt;+&lt;/span&gt;m) (xs &lt;span&gt;&amp;lt;*&amp;gt;&lt;/span&gt; delayKey n ys)&lt;/span&gt;

&lt;span&gt;&lt;span&gt;runStable ::&lt;/span&gt; (&lt;span&gt;Applicative&lt;/span&gt; f, &lt;span&gt;Ord&lt;/span&gt; k) &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; k f a &lt;span&gt;-&amp;gt;&lt;/span&gt; f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; runHeap &lt;span&gt;.&lt;/span&gt; heap&lt;/span&gt;

&lt;span&gt;&lt;span&gt;stable ::&lt;/span&gt; &lt;span&gt;Ord&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; k &lt;span&gt;-&amp;gt;&lt;/span&gt; f a &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; k f a&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;Stable&lt;/span&gt; &lt;span&gt;1&lt;/span&gt; (phase (k &lt;span&gt;:*&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;) fa)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a pure, optimally efficient implementation of &lt;code&gt;&lt;span&gt;Phases&lt;/span&gt;&lt;/code&gt; ordered
by an arbitrary total-ordered key.&lt;/p&gt;
&lt;h1&gt;Local Computation in a
Monadic Heap&lt;/h1&gt;
&lt;p&gt;In &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;)&lt;/span&gt;,
I developed a monadic heap based on the free monad transformer.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;newtype&lt;/span&gt; &lt;span&gt;Search&lt;/span&gt; k a &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Search&lt;/span&gt; {&lt;span&gt; runSearch ::&lt;/span&gt; [&lt;span&gt;Either&lt;/span&gt; a (k, &lt;span&gt;Search&lt;/span&gt; k a)] }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This type is equivalent to the &lt;a href="https://hackage.haskell.org/package/free-5.2/docs/Control-Monad-Trans-Free.html#t:FreeT"&gt;free
monad transformer&lt;/a&gt; over the list monad and &lt;code&gt;(,) k&lt;/code&gt; functor (i.e. the writer
monad).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Search&lt;/span&gt; k a ≅ &lt;span&gt;FreeT&lt;/span&gt; ((,) k) [] a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the paper &lt;span&gt;(&lt;a href="https://doisinkidney.com/posts/2026-03-03-monus-heaps.html#ref-kidney_algebras_2021"&gt;2021&lt;/a&gt;)&lt;/span&gt; we extended the type to become a
full monad transformer, replacing lists with &lt;code&gt;&lt;span&gt;ListT&lt;/span&gt;&lt;/code&gt;. This
let us order the effects according to the weight &lt;code&gt;k&lt;/code&gt;; however, for this example we only
need the simplified type, which lets us order the values according to
&lt;code&gt;k&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;&lt;span&gt;Search&lt;/span&gt;&lt;/code&gt; type
follows the structure of a pairing heap (although not as closely as the
version above). However, this type is interesting because
&lt;em&gt;semantically&lt;/em&gt; it needs the weights to be stored as differences,
rather than absolute weights. As a free monad transformer, the &lt;code&gt;&lt;span&gt;Search&lt;/span&gt;&lt;/code&gt; type
layers effects on top of each other; we can later interpret those layers
by collapsing them together using the monadic &lt;code&gt;join&lt;/code&gt;. In the case of &lt;code&gt;&lt;span&gt;Search&lt;/span&gt;&lt;/code&gt;, those
layers are drawn from the list monad and the &lt;code&gt;(,) k&lt;/code&gt; functor (writer monad). That
means that if we have some heap representing the tree from above:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Search&lt;/span&gt; [ &lt;span&gt;Right&lt;/span&gt; (a, &lt;span&gt;Search&lt;/span&gt; [ &lt;span&gt;Right&lt;/span&gt; (b, &lt;span&gt;Search&lt;/span&gt; [ &lt;span&gt;Right&lt;/span&gt; (d, &lt;span&gt;Search&lt;/span&gt; [&lt;span&gt;Left&lt;/span&gt; x])&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Right&lt;/span&gt; (e, &lt;span&gt;Search&lt;/span&gt; [&lt;span&gt;Left&lt;/span&gt; y])])&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Right&lt;/span&gt; (c, &lt;span&gt;Search&lt;/span&gt; [&lt;span&gt;Left&lt;/span&gt; z])])]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we collapse this computation down to the leaves, the weights we
will get are the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; b &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; d, x), (a &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; b &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; e, y), (a &lt;span&gt;&amp;lt;&amp;gt;&lt;/span&gt; c, z)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, if we want the weights to line up properly, we need to store the
differences.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mergeS ::&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; [(k, &lt;span&gt;Search&lt;/span&gt; k a)] &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Maybe&lt;/span&gt; (k, &lt;span&gt;Search&lt;/span&gt; k a)&lt;/span&gt;
&lt;span&gt;=&lt;/span&gt; &lt;span&gt;Nothing&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:&lt;/span&gt;xs) &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Just&lt;/span&gt; (mergeS' x xs)&lt;/span&gt;
&lt;span&gt;where&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; x1&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; x1 &lt;span&gt;&amp;lt;+&amp;gt;&lt;/span&gt; x2&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:&lt;/span&gt;x3&lt;span&gt;:&lt;/span&gt;xs) &lt;span&gt;=&lt;/span&gt; (x1 &lt;span&gt;&amp;lt;+&amp;gt;&lt;/span&gt; x2) &lt;span&gt;&amp;lt;+&amp;gt;&lt;/span&gt; mergeS' x3 xs&lt;/span&gt;

&lt;span&gt;&lt;span&gt;Search&lt;/span&gt; xs) &lt;span&gt;&amp;lt;+&amp;gt;&lt;/span&gt; (yw, &lt;span&gt;Search&lt;/span&gt; ys)&lt;/span&gt;
&lt;span&gt;&lt;span&gt;|&lt;/span&gt; xw &lt;span&gt;&amp;lt;=&lt;/span&gt; yw  &lt;span&gt;=&lt;/span&gt; (xw, &lt;span&gt;Search&lt;/span&gt; (&lt;span&gt;Right&lt;/span&gt; (yw ∸ xw, &lt;span&gt;Search&lt;/span&gt; ys) &lt;span&gt;:&lt;/span&gt; xs))&lt;/span&gt;
&lt;span&gt;&lt;span&gt;|&lt;/span&gt; &lt;span&gt;otherwise&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; (yw, &lt;span&gt;Search&lt;/span&gt; (&lt;span&gt;Right&lt;/span&gt; (xw ∸ yw, &lt;span&gt;Search&lt;/span&gt; xs) &lt;span&gt;:&lt;/span&gt; ys))&lt;/span&gt;

&lt;span&gt;&lt;span&gt;popMins ::&lt;/span&gt; &lt;span&gt;Monus&lt;/span&gt; k &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Search&lt;/span&gt; k a &lt;span&gt;-&amp;gt;&lt;/span&gt; ([a], &lt;span&gt;Maybe&lt;/span&gt; (k, &lt;span&gt;Search&lt;/span&gt; k a))&lt;/span&gt;
&lt;span&gt;&lt;span&gt;=&lt;/span&gt; &lt;span&gt;fmap&lt;/span&gt; mergeS &lt;span&gt;.&lt;/span&gt; partitionEithers &lt;span&gt;.&lt;/span&gt; runSearch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The technique of “don’t store the absolute value, store the
difference” seems to be generally quite useful; I think that monuses are
a handy algebra to keep in mind whenever that technique looks like it
might be needed. The &lt;code&gt;&lt;span&gt;Key&lt;/span&gt;&lt;/code&gt; monus
above is closely related to the factorial numbers, and the trick I used
in &lt;a href="https://doisinkidney.com/posts/2019-03-24-permutations-by-sorting.html"&gt;this&lt;/a&gt; post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;References&lt;/h2&gt;

&lt;div&gt;
Amer, K. 1984. &lt;span&gt;“Equationally complete classes of commutative
monoids with monus.”&lt;/span&gt; &lt;em&gt;algebra universalis&lt;/em&gt; 18 (1)
(February): 129–131. doi:&lt;a href="https://doi.org/10.1007/BF01182254"&gt;10.1007/BF01182254&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Blöndal, Baldur. 2025a. &lt;span&gt;“Generalized multi-phase
compiler/concurrency.”&lt;/span&gt; &lt;em&gt;reddit&lt;/em&gt;. &lt;a href="https://www.reddit.com/r/haskell/comments/1m25fw8/generalized_multiphase_compilerconcurrency/"&gt;https://www.reddit.com/r/haskell/comments/1m25fw8/generalized_multiphase_compilerconcurrency/&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
———. 2025b. &lt;span&gt;“Phases using &lt;span&gt;Vault&lt;/span&gt;.”&lt;/span&gt;
&lt;em&gt;reddit&lt;/em&gt;. &lt;a href="https://www.reddit.com/r/haskell/comments/1msvwzd/phases_using_vault/"&gt;https://www.reddit.com/r/haskell/comments/1msvwzd/phases_using_vault/&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Easterly, Noah. 2019. &lt;span&gt;“Functions and newtype wrappers for
traversing &lt;span&gt;Trees&lt;/span&gt;: Rampion/tree-traversals.”&lt;/span&gt; &lt;a href="https://github.com/rampion/tree-traversals"&gt;https://github.com/rampion/tree-traversals&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Fredman, Michael L., Robert Sedgewick, Daniel D. Sleator, and Robert E.
Tarjan. 1986. &lt;span&gt;“The pairing heap: &lt;span&gt;A&lt;/span&gt; new form of
self-adjusting heap.”&lt;/span&gt; &lt;em&gt;Algorithmica&lt;/em&gt; 1 (1-4) (January):
111–129. doi:&lt;a href="https://doi.org/10.1007/BF01840439"&gt;10.1007/BF01840439&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Gibbons, Jeremy, Donnacha Oisín Kidney, Tom Schrijvers, and Nicolas Wu.
2022. &lt;span&gt;“Breadth-&lt;span&gt;First Traversal&lt;/span&gt;
via &lt;span&gt;Staging&lt;/span&gt;.”&lt;/span&gt; In &lt;em&gt;Mathematics of &lt;span&gt;Program
Construction&lt;/span&gt;&lt;/em&gt;, ed by. Ekaterina Komendantskaya, 1–33. Cham:
Springer International Publishing. doi:&lt;a href="https://doi.org/10.1007/978-3-031-16912-0_1"&gt;10.1007/978-3-031-16912-0_1&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
———. 2023. &lt;span&gt;“Phases in &lt;span&gt;Software Architecture&lt;/span&gt;.”&lt;/span&gt;
In &lt;em&gt;Proceedings of the 1st &lt;span&gt;ACM SIGPLAN International
Workshop&lt;/span&gt; on &lt;span&gt;Functional Software Architecture&lt;/span&gt;&lt;/em&gt;,
29–33. &lt;span&gt;FUNARCH&lt;/span&gt; 2023. New York, NY, USA: Association for
Computing Machinery. doi:&lt;a href="https://doi.org/10.1145/3609025.3609479"&gt;10.1145/3609025.3609479&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Kidney, Donnacha Oisín, and Nicolas Wu. 2021. &lt;span&gt;“Algebras for
weighted search.”&lt;/span&gt; &lt;em&gt;Proceedings of the ACM on Programming
Languages&lt;/em&gt; 5 (ICFP) (August): 72:1–72:30. doi:&lt;a href="https://doi.org/10.1145/3473577"&gt;10.1145/3473577&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
———. 2025. &lt;span&gt;“Formalising &lt;span&gt;Graph Algorithms&lt;/span&gt; with
&lt;span&gt;Coinduction&lt;/span&gt;.”&lt;/span&gt; &lt;em&gt;Proc. ACM Program. Lang.&lt;/em&gt; 9
(POPL) (January): 56:1657–56:1686. doi:&lt;a href="https://doi.org/10.1145/3704892"&gt;10.1145/3704892&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Larkin, Daniel H., Siddhartha Sen, and Robert E. Tarjan. 2013. &lt;span&gt;“A
&lt;span&gt;Back-to-Basics Empirical Study&lt;/span&gt; of
&lt;span&gt;Priority Queues&lt;/span&gt;.”&lt;/span&gt; In &lt;em&gt;2014
&lt;span&gt;Proceedings&lt;/span&gt; of the &lt;span&gt;Meeting&lt;/span&gt; on &lt;span&gt;Algorithm
Engineering&lt;/span&gt; and &lt;span&gt;Experiments&lt;/span&gt;
(&lt;span&gt;ALENEX&lt;/span&gt;)&lt;/em&gt;, 61–72. Proceedings. &lt;span&gt;Society for
Industrial and Applied Mathematics&lt;/span&gt;. doi:&lt;a href="https://doi.org/10.1137/1.9781611973198.7"&gt;10.1137/1.9781611973198.7&lt;/a&gt;.
&lt;/div&gt;
&lt;div&gt;
Visscher, Sjoerd. 2025. &lt;span&gt;“Phases with any &lt;span&gt;Ord&lt;/span&gt; key
type.”&lt;/span&gt; &lt;a href="https://gist.github.com/sjoerdvisscher/bf282a050f0681e2f737908e254c4061"&gt;https://gist.github.com/sjoerdvisscher/bf282a050f0681e2f737908e254c4061&lt;/a&gt;.
&lt;/div&gt;

&lt;/div&gt;
</ns0:encoded></item><item><title>Chris Reade: PenroseKiteDart User Guide</title><guid isPermaLink="false">http://readerunner.wordpress.com/?p=251</guid><link>https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/</link><description>&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;(Updated February 2026 for PenroseKiteDart version 1.6.1)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PenroseKiteDart is a Haskell package with tools to experiment with finite tilings of Penrose’s Kites and Darts. It uses the &lt;a href="https://diagrams.github.io"&gt;Haskell Diagrams&lt;/a&gt; package for drawing tilings. As well as providing drawing tools, this package introduces tile graphs (&lt;code&gt;Tgraphs&lt;/code&gt;) for describing finite tilings. (I would like to thank Stephen Huggett for suggesting planar graphs as a way to reperesent the tilings).&lt;/p&gt;
&lt;p&gt;This document summarises the design and use of the PenroseKiteDart package.&lt;/p&gt;
&lt;p&gt;PenroseKiteDart package is now available on &lt;a href="https://hackage.haskell.org"&gt;Hackage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The source files are available on GitHub at &lt;a href="https://github.com/chrisreade/PenroseKiteDart"&gt;https://github.com/chrisreade/PenroseKiteDart&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is a small art gallery of examples created with PenroseKiteDart &lt;a href="https://github.com/chrisreade/PenroseKiteDart/tree/master/ArtGallery"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Index&lt;/strong&gt;&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#1"&gt;About Penrose’s Kites and Darts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#2"&gt;Using the PenroseKiteDart Package&lt;/a&gt; (initial set up).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#3"&gt;Overview of Types and Operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#4"&gt;Drawing in more detail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#5"&gt;Forcing in more detail&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#6"&gt;Advanced Operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2024/04/08/penrosekitedart-user-guides/#7"&gt;Other Reading&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a name="1"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="about-penroses-kites-and-darts"&gt;1. About Penroseâ€™s Kites and Darts&lt;/h2&gt;
&lt;h3 id="the-tiles"&gt;The Tiles&lt;/h3&gt;
&lt;p&gt;In figure 1 we show a dart and a kite. All angles are multiples of &lt;img alt="36^{\circ}" class="latex" src="https://s0.wp.com/latex.php?latex=36%5E%7B%5Ccirc%7D&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002" /&gt; (a tenth of a full turn). If the shorter edges are of length 1, then the longer edges are of length &lt;img alt="\phi" class="latex" src="https://s0.wp.com/latex.php?latex=%5Cphi&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002" /&gt;, where &lt;img alt="\phi = (1+ \sqrt{5})/ 2" class="latex" src="https://s0.wp.com/latex.php?latex=%5Cphi+%3D+%281%2B+%5Csqrt%7B5%7D%29%2F+2&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002" /&gt; is the golden ratio.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 1: The Dart and Kite Tiles" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/geomtiles.png?w=625" /&gt;&lt;figcaption&gt;Figure 1: The Dart and Kite Tiles&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id="aperiodic-infinite-tilings"&gt;Aperiodic Infinite Tilings&lt;/h3&gt;
&lt;p&gt;What is interesting about these tiles is:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It is possible to tile the entire plane with kites and darts in an aperiodic way.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Such a tiling is non-periodic and does not contain arbitrarily large periodic regions or patches.&lt;/p&gt;
&lt;p&gt;The possibility of aperiodic tilings with kites and darts was discovered by Sir Roger Penrose in 1974. There are other shapes with this property, including a chiral aperiodic monotile discovered in 2023 by Smith, Myers, Kaplan, Goodman-Strauss. (See the Penrose Tiling &lt;a href="https://en.wikipedia.org/wiki/Penrose_tiling"&gt;Wikipedia page&lt;/a&gt; for the history of aperiodic tilings)&lt;/p&gt;
&lt;p&gt;This package is entirely concerned with Penrose’s kite and dart tilings also known as P2 tilings.&lt;/p&gt;
&lt;h3 id="legal-tilings"&gt;Legal Tilings&lt;/h3&gt;
&lt;p&gt;In figure 2 we add a temporary green line marking purely to illustrate a rule for making &lt;em&gt;legal tilings&lt;/em&gt;. The purpose of the rule is to exclude the possibility of periodic tilings.&lt;/p&gt;
&lt;p&gt;If all tiles are marked as shown, then whenever tiles come together at a point, they must all be marked or must all be unmarked at that meeting point. So, for example, each long edge of a kite can be placed legally on only &lt;em&gt;one&lt;/em&gt; of the two long edges of a dart. The kite wing vertex (which is marked) has to go next to the dart tip vertex (which is marked) and cannot go next to the dart wing vertex (which is unmarked) for a legal tiling.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 2: Marked Dart and Kite" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/markedtiles2.png?w=625" /&gt;&lt;figcaption&gt;Figure 2: Marked Dart and Kite&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id="correct-tilings"&gt;Correct Tilings&lt;/h3&gt;
&lt;p&gt;Unfortunately, having a finite legal tiling is not enough to guarantee you can continue the tiling without getting stuck. Finite legal tilings which can be continued to cover the entire plane are called &lt;em&gt;correct&lt;/em&gt; and the others (which are doomed to get stuck) are called &lt;em&gt;incorrect&lt;/em&gt;. This means that decomposition and forcing (described later) become important tools for constructing correct finite tilings.&lt;/p&gt;
&lt;p&gt;&lt;a name="2"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="using-the-penrosekitedart-package"&gt;2. Using the PenroseKiteDart Package&lt;/h2&gt;
&lt;p&gt;You will need the Haskell Diagrams package (See &lt;a href="https://diagrams.github.io"&gt;Haskell Diagrams&lt;/a&gt;) as well as this package (PenroseKiteDart). When these are installed, you can produce diagrams with a Main.hs module. This should import a chosen backend for diagrams such as the default (SVG) along with &lt;code&gt;Diagrams.Prelude&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;module&lt;/span&gt; &lt;span&gt;Main&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: blue; font-weight: bold;"&gt;where&lt;/span&gt;
    
    &lt;span style="color: blue; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span&gt;Diagrams.Backend.SVG.CmdLine&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span&gt;Diagrams.Prelude&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Penrose’s Kite and Dart tilings, you also need to import the &lt;code&gt;PKD&lt;/code&gt; module and (optionally) the &lt;code&gt;TgraphExamples&lt;/code&gt; module.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span&gt;PKD&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;import&lt;/span&gt; &lt;span&gt;TgraphExamples&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then to ouput &lt;code&gt;someExample&lt;/code&gt; figure&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;fig&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt;&lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;fig&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;someExample&lt;/span&gt;

    &lt;span&gt;main&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;IO&lt;/span&gt; &lt;span&gt;()&lt;/span&gt;
    &lt;span&gt;main&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;mainWith&lt;/span&gt; &lt;span&gt;fig&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the token &lt;code&gt;B&lt;/code&gt; is used in the diagrams package to represent the chosen backend for output. So a diagram has type &lt;code&gt;Diagram B&lt;/code&gt;. In this case &lt;code&gt;B&lt;/code&gt; is bound to SVG by the import of the SVG backend. When the compiled module is executed it will generate an SVG file. (See &lt;a href="https://diagrams.github.io"&gt;Haskell Diagrams&lt;/a&gt; for more details on producing diagrams and using alternative backends).&lt;/p&gt;
&lt;p&gt;&lt;a name="3"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="overview-of-types-and-operations"&gt;3. Overview of Types and Operations&lt;/h2&gt;
&lt;h3 id="half-tiles"&gt;Half-Tiles&lt;/h3&gt;
&lt;p&gt;In order to implement operations on tilings (&lt;code&gt;decompose&lt;/code&gt; in particular), we work with half-tiles. These are illustrated in figure 3 and labelled &lt;code&gt;RD&lt;/code&gt; (right dart), &lt;code&gt;LD&lt;/code&gt; (left dart), &lt;code&gt;LK&lt;/code&gt; (left kite), &lt;code&gt;RK&lt;/code&gt; (right kite). The &lt;em&gt;join&lt;/em&gt; edges where left and right halves come together are shown with dotted lines, leaving one short edge and one long edge on each half-tile (excluding the join edge). We have shown a red dot at the vertex we regard as the origin of each half-tile (the tip of a half-dart and the base of a half-kite).&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 3: Half-Tile pieces showing join edges (dashed) and origin vertices (red dots)" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/newpiecesfig.png?w=625" /&gt;&lt;figcaption&gt;Figure 3: Half-Tile pieces showing join edges (dashed) and origin vertices (red dots)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The labels are actually data constructors introduced with type operator &lt;code&gt;HalfTile&lt;/code&gt; which has an argument type (&lt;code&gt;rep&lt;/code&gt;) to allow for more than one representation of the half-tiles.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;data&lt;/span&gt; &lt;span&gt;HalfTile&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; 
      &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;LD&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span style="color: green;"&gt;-- Left Dart&lt;/span&gt;
      &lt;span style="color: red;"&gt;|&lt;/span&gt; &lt;span&gt;RD&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span style="color: green;"&gt;-- Right Dart&lt;/span&gt;
      &lt;span style="color: red;"&gt;|&lt;/span&gt; &lt;span&gt;LK&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span style="color: green;"&gt;-- Left Kite&lt;/span&gt;
      &lt;span style="color: red;"&gt;|&lt;/span&gt; &lt;span&gt;RK&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span style="color: green;"&gt;-- Right Kite&lt;/span&gt;
      &lt;span style="color: blue; font-weight: bold;"&gt;deriving&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Eq&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="tgraphs"&gt;Tgraphs&lt;/h3&gt;
&lt;p&gt;We introduce tile graphs (&lt;code&gt;Tgraph&lt;/code&gt;s) which provide a simple planar graph representation for finite patches of tiles. For &lt;code&gt;Tgraph&lt;/code&gt;s we first specialise &lt;code&gt;HalfTile&lt;/code&gt; with a triple of vertices (positive integers) to make a &lt;code&gt;TileFace&lt;/code&gt; such as &lt;code&gt;RD(1,2,3)&lt;/code&gt;, where the vertices go clockwise round the half-tile triangle starting with the origin.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt;  &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;HalfTile&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt;    &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt;  &lt;span style="color: green;"&gt;-- must be positive&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;makeTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then constructs a &lt;code&gt;Tgraph&lt;/code&gt; from a &lt;code&gt;TileFace&lt;/code&gt; list after checking the &lt;code&gt;TileFace&lt;/code&gt;s satisfy certain properties (described below). We also have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;faces&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to retrieve the &lt;code&gt;TileFace&lt;/code&gt; list from a &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As an example, the &lt;code&gt;fool&lt;/code&gt; (short for &lt;em&gt;fool’s kite&lt;/em&gt; and also called an &lt;em&gt;ace&lt;/em&gt; in the literature) consists of two kites and a dart (= 4 half-kites and 2 half-darts):&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;fool&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;fool&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;makeTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;RD&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;1&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;2&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;3&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;LD&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;1&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;3&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;4&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;   &lt;span style="color: green;"&gt;-- right and left dart&lt;/span&gt;
                      &lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;LK&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;5&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;3&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;2&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;RK&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;5&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;2&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;7&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;   &lt;span style="color: green;"&gt;-- left and right kite&lt;/span&gt;
                      &lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;RK&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;5&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;4&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;3&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;LK&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;5&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;6&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span class="hs-num"&gt;4&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;   &lt;span style="color: green;"&gt;-- right and left kite&lt;/span&gt;
                      &lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To produce a diagram, we simply &lt;code&gt;draw&lt;/code&gt; the &lt;code&gt;Tgraph&lt;/code&gt;&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;fool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will produce the diagram on the left in figure 4.&lt;/p&gt;
&lt;p&gt;Alternatively,&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;drawj&lt;/span&gt; &lt;span&gt;fool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will produce the diagram on the right in figure 4 (showing vertex labels and dashed join edges).&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 4: Diagram of fool without labels and join edges (left), and with (right)" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/newfool.png?w=625" /&gt;&lt;figcaption&gt;Figure 4: Diagram of &lt;code&gt;fool&lt;/code&gt; without labels and join edges (left), and with (right)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;When any (non-empty) &lt;code&gt;Tgraph&lt;/code&gt; is drawn, a default orientation and scale are chosen based on the lowest numbered join edge. This is aligned on the positive x-axis with length 1 (for darts) or length &lt;img alt="\phi" class="latex" src="https://s0.wp.com/latex.php?latex=%5Cphi&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002" /&gt; (for kites).&lt;/p&gt;
&lt;h3 id="tgraph-properties"&gt;Tgraph Properties&lt;/h3&gt;
&lt;p&gt;Tgraphs are actually implemented as&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;newtype&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;
                     &lt;span style="color: blue; font-weight: bold;"&gt;deriving&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but the data constructor &lt;code&gt;Tgraph&lt;/code&gt; is not exported to avoid accidentally by-passing checks for the required properties. The properties checked by &lt;code&gt;makeTgraph&lt;/code&gt; ensure the &lt;code&gt;Tgraph&lt;/code&gt; represents a legal tiling as a planar graph with positive vertex numbers, and that the collection of half-tile faces are both connected and have no crossing boundaries (see note below). Finally, there is a check to ensure two or more distinct vertex numbers are not used to represent the same vertex of the graph (a &lt;em&gt;touching vertex&lt;/em&gt; check). An error is raised if there is a problem.&lt;/p&gt;
&lt;p&gt;Note: If the &lt;code&gt;TileFace&lt;/code&gt;s are faces of a planar graph there will also be exterior (untiled) regions, and in graph theory these would also be called faces of the graph. To avoid confusion, we will refer to these only as &lt;em&gt;exterior regions&lt;/em&gt;, and unless otherwise stated, &lt;em&gt;face&lt;/em&gt; will mean a &lt;code&gt;TileFace&lt;/code&gt;. We can then define the boundary of a list of &lt;code&gt;TileFace&lt;/code&gt;s as the edges of the exterior regions. There is a &lt;em&gt;crossing boundary&lt;/em&gt; if the boundary crosses itself at a vertex. We exclude crossing boundaries from &lt;code&gt;Tgraph&lt;/code&gt;s because they prevent us from calculating relative positions of tiles locally and create touching vertex problems.&lt;/p&gt;
&lt;p&gt;For convenience, in addition to &lt;code&gt;makeTgraph&lt;/code&gt;, we also have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;makeUncheckedTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;checkedTgraph&lt;/span&gt;   &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first of these (performing no checks) is useful when you know the required properties hold. The second performs the same checks as &lt;code&gt;makeTgraph&lt;/code&gt; except that it omits the touching vertex check. This could be used, for example, when making a &lt;code&gt;Tgraph&lt;/code&gt; from a sub-collection of &lt;code&gt;TileFace&lt;/code&gt;s of another &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="main-tiling-operations"&gt;Main Tiling Operations&lt;/h3&gt;
&lt;p&gt;There are three key operations on finite tilings, namely&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;decompose&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;force&lt;/span&gt;     &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;compose&lt;/span&gt;   &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="decompose"&gt;Decompose&lt;/h4&gt;
&lt;p&gt;Decomposition (also called &lt;em&gt;deflation&lt;/em&gt;) works by splitting each half-tile into either 2 or 3 new (&lt;em&gt;smaller scale&lt;/em&gt;) half-tiles, to produce a new tiling. The fact that this is possible, is used to establish the existence of infinite aperiodic tilings with kites and darts. Since our &lt;code&gt;Tgraph&lt;/code&gt;s have abstracted away from scale, the result of decomposing a &lt;code&gt;Tgraph&lt;/code&gt; is just another &lt;code&gt;Tgraph&lt;/code&gt;. However if we wish to compare before and after with a drawing, the latter should be scaled by a factor &lt;img alt="1/{\phi} = \phi - 1" class="latex" src="https://s0.wp.com/latex.php?latex=1%2F%7B%5Cphi%7D+%3D+%5Cphi+-+1&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002" /&gt; times the scale of the former, to reflect the change in scale.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 5: fool (left) and decompose fool (right)" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/foolandfoold.png?w=625" /&gt;&lt;figcaption&gt;Figure 5: &lt;code&gt;fool&lt;/code&gt; (left) and &lt;code&gt;decompose fool&lt;/code&gt; (right)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We can, of course, iterate &lt;code&gt;decompose&lt;/code&gt; to produce an infinite list of finer and finer decompositions of a &lt;code&gt;Tgraph&lt;/code&gt;&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;decompositions&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;
    &lt;span&gt;decompositions&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;iterate&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id="force"&gt;Force&lt;/h4&gt;
&lt;p&gt;Force works by adding any &lt;code&gt;TileFace&lt;/code&gt;s on the boundary edges of a &lt;code&gt;Tgraph&lt;/code&gt; which are &lt;em&gt;forced&lt;/em&gt;. That is, where there is only one legal choice of &lt;code&gt;TileFace&lt;/code&gt; addition consistent with the seven possible vertex types. Such additions are continued until either (i) there are no more forced cases, in which case a final (forced) &lt;code&gt;Tgraph&lt;/code&gt; is returned, or (ii) the process finds the tiling is stuck, in which case an error is raised indicating an incorrect tiling. [In the latter case, the argument to &lt;code&gt;force&lt;/code&gt; must have been an incorrect tiling, because the forced additions cannot produce an incorrect tiling starting from a correct tiling.]&lt;/p&gt;
&lt;p&gt;An example is shown in figure 6. When forced, the &lt;code&gt;Tgraph&lt;/code&gt; on the left produces the result on the right. The original is highlighted in red in the result to show what has been added.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 6: A Tgraph (left) and its forced result (right) with the original shown red" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/fooldandforce.png?w=625" /&gt;&lt;figcaption&gt;Figure 6: A Tgraph (left) and its forced result (right) with the original shown red&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4 id="compose"&gt;Compose&lt;/h4&gt;
&lt;p&gt;Composition (also called &lt;em&gt;inflation&lt;/em&gt;) is an opposite to &lt;code&gt;decompose&lt;/code&gt; but this has complications for finite tilings, so it is not simply an inverse. (See &lt;a href="https://readerunner.wordpress.com/2023/09/12/graphs-kites-and-darts-and-theorems/"&gt;Graphs,Kites and Darts and Theorems&lt;/a&gt; for more discussion of the problems). Figure 7 shows a &lt;code&gt;Tgraph&lt;/code&gt; (left) with the result of composing (right) where we have also shown (in pale green) the faces of the original that are not included in the composition – the remainder faces.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 7: A Tgraph (left) and its (part) composed result (right) with the remainder faces shown pale green" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/pcomposeexample.png?w=625" /&gt;&lt;figcaption&gt;Figure 7: A Tgraph (left) and its (part) composed result (right) with the remainder faces shown pale green&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Under some circumstances composing can fail to produce a &lt;code&gt;Tgraph&lt;/code&gt; because there are crossing boundaries in the resulting &lt;code&gt;TileFaces&lt;/code&gt;. However, we have established that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;g&lt;/code&gt; is a forced &lt;code&gt;Tgraph&lt;/code&gt;, then &lt;code&gt;compose g&lt;/code&gt; is defined and it is also a forced &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="try-results"&gt;Try Results&lt;/h3&gt;
&lt;p&gt;It is convenient to use types of the form &lt;code&gt;Try a&lt;/code&gt; for results where we know there can be a failure. For example, &lt;code&gt;compose&lt;/code&gt; can fail if the result does not pass the connected and no crossing boundary check, and &lt;code&gt;force&lt;/code&gt; can fail if its argument is an incorrect &lt;code&gt;Tgraph&lt;/code&gt;. In situations when you would like to continue some computation rather than raise an error when there is a failure, use a &lt;em&gt;try&lt;/em&gt; version of a function.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryCompose&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;tryForce&lt;/span&gt;   &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define &lt;code&gt;Try&lt;/code&gt; as a synonym for &lt;code&gt;Either ShowS&lt;/code&gt; (which is a monad) in module &lt;code&gt;Tgraph.Try&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Try a = Either ShowS a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Note &lt;code&gt;ShowS&lt;/code&gt; is &lt;code&gt;String -&amp;gt; String&lt;/code&gt;). Successful results have the form &lt;code&gt;Right r&lt;/code&gt; (for some correct result &lt;code&gt;r&lt;/code&gt;) and failure results have the form &lt;code&gt;Left (s&amp;lt;&amp;gt;)&lt;/code&gt; (where &lt;code&gt;s&lt;/code&gt; is a &lt;code&gt;String&lt;/code&gt; describing the problem as a failure report).&lt;/p&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;runTry&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;runTry&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;either&lt;/span&gt; &lt;span&gt;error&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will retrieve a correct result but raise an error for failure cases. This means we can always derive an error raising version from a try version of a function by composing with &lt;code&gt;runTry&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;
    &lt;span&gt;compose&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;tryCompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="elementary-tgraph-and-tileface-operations"&gt;Elementary Tgraph and TileFace Operations&lt;/h3&gt;
&lt;p&gt;The module &lt;code&gt;Tgraph.Prelude&lt;/code&gt; defines elementary operations on &lt;code&gt;Tgraph&lt;/code&gt;s relating vertices, directed edges, and faces. We describe a few of them here.&lt;/p&gt;
&lt;p&gt;When we need to refer to particular vertices of a &lt;code&gt;TileFace&lt;/code&gt; we use&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;originV&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt; &lt;span style="color: green;"&gt;-- the first vertex - red dot in figure 2&lt;/span&gt;
    &lt;span&gt;oppV&lt;/span&gt;    &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt; &lt;span style="color: green;"&gt;-- the vertex at the opposite end of the join edge from the origin&lt;/span&gt;
    &lt;span&gt;wingV&lt;/span&gt;   &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt; &lt;span style="color: green;"&gt;-- the vertex not on the join edge&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A directed edge is represented as a pair of vertices.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;(a,b)&lt;/code&gt; is regarded as a directed edge from a to b.&lt;/p&gt;
&lt;p&gt;When we need to refer to particular edges of a &lt;code&gt;TileFace&lt;/code&gt; we use&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;joinE&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;  &lt;span style="color: green;"&gt;-- shown dotted in figure 2&lt;/span&gt;
    &lt;span&gt;shortE&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;  &lt;span style="color: green;"&gt;-- the non-join short edge&lt;/span&gt;
    &lt;span&gt;longE&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;  &lt;span style="color: green;"&gt;-- the non-join long edge&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which are all directed clockwise round the &lt;code&gt;TileFace&lt;/code&gt;. In contrast, &lt;code&gt;joinOfTile&lt;/code&gt; is always directed away from the origin vertex, so is not clockwise for right darts or for left kites:&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;joinOfTile&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;
    &lt;span&gt;joinOfTile&lt;/span&gt; &lt;span&gt;face&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;originV&lt;/span&gt; &lt;span&gt;face&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;oppV&lt;/span&gt; &lt;span&gt;face&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the special case that a list of directed edges is symmetrically closed [(b,a) is in the list whenever (a,b) is in the list] we can think of this as an edge list rather than just a directed edge list.&lt;/p&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;internalEdges&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;produces an edge list, whereas&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;boundary&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;produces single directions. Each directed edge in the resulting boundary will have a &lt;code&gt;TileFace&lt;/code&gt; on the left and an exterior region on the right. The function&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;dedges&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;produces all the directed edges obtained by going clockwise round each &lt;code&gt;TileFace&lt;/code&gt; so not every edge in the list has an inverse in the list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There is now a class &lt;code&gt;HasFaces&lt;/code&gt; (introduced in version 1.4) which includes instances for both &lt;code&gt;Tgraph&lt;/code&gt; and &lt;code&gt;[TileFace]&lt;/code&gt; and others. This allows some generalisations. For example&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;faces&lt;/span&gt;         &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;
    &lt;span&gt;internalEdges&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;
    &lt;span&gt;boundary&lt;/span&gt;      &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; 
    &lt;span&gt;dedges&lt;/span&gt;        &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; 
    &lt;span&gt;nullFaces&lt;/span&gt;     &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="patches-scaled-and-positioned-tilings"&gt;Patches (Scaled and Positioned Tilings)&lt;/h3&gt;
&lt;p&gt;Behind the scenes, when a &lt;code&gt;Tgraph&lt;/code&gt; is drawn, each &lt;code&gt;TileFace&lt;/code&gt; is converted to a &lt;code&gt;Piece&lt;/code&gt;. A &lt;code&gt;Piece&lt;/code&gt; is another specialisation of &lt;code&gt;HalfTile&lt;/code&gt; using a two dimensional vector to indicate the length and direction of the join edge of the half-tile (from the &lt;code&gt;originV&lt;/code&gt; to the &lt;code&gt;oppV&lt;/code&gt;), thus fixing its scale and orientation. The whole &lt;code&gt;Tgraph&lt;/code&gt; then becomes a list of located &lt;code&gt;Piece&lt;/code&gt;s called a &lt;code&gt;Patch&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;HalfTile&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;V2&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;Patch&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Located&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Piece&lt;/code&gt; drawing functions derive vectors for other edges of a half-tile piece from its join edge vector. In particular (in the &lt;code&gt;TileLib&lt;/code&gt; module) we have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;drawPiece&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;darawjPiece&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;fillPieceDK&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the first draws the non-join edges of a &lt;code&gt;Piece&lt;/code&gt;, the second does the same but adds a faint dashed line for the join edge, and the third takes two colours – one for darts and one for kites, which are used to fill the piece as well as using &lt;code&gt;drawPiece&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Patch&lt;/code&gt; is an instance of class &lt;code&gt;Transformable&lt;/code&gt; so a &lt;code&gt;Patch&lt;/code&gt; can be scaled, rotated, and translated.&lt;/p&gt;
&lt;h3 id="vertex-patches"&gt;Vertex Patches&lt;/h3&gt;
&lt;p&gt;It is useful to have an intermediate form between &lt;code&gt;Tgraph&lt;/code&gt;s and &lt;code&gt;Patch&lt;/code&gt;es, that contains information about both the location of vertices (as 2D points), and the abstract &lt;code&gt;TileFace&lt;/code&gt;s. This allows us to introduce labelled drawing functions (to show the vertex labels) which we then extend to &lt;code&gt;Tgraph&lt;/code&gt;s. We call the intermediate form a &lt;code&gt;VPatch&lt;/code&gt; (short for Vertex Patch).&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;VertexLocMap&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;IntMap.IntMap&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Point&lt;/span&gt; &lt;span&gt;V2&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;data&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;{&lt;/span&gt;&lt;span&gt;vLocs&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;VertexLocMap&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;  &lt;span&gt;vpFaces&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;span style="color: red;"&gt;}&lt;/span&gt; &lt;span style="color: blue; font-weight: bold;"&gt;deriving&lt;/span&gt; &lt;span&gt;Show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;makeVP&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;calculates vertex locations using a default orientation and scale.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;VPatch&lt;/code&gt; is made an instance of class &lt;code&gt;Transformable&lt;/code&gt; so a &lt;code&gt;VPatch&lt;/code&gt; can also be scaled and rotated.&lt;/p&gt;
&lt;p&gt;One essential use of this intermediate form is to be able to draw a &lt;code&gt;Tgraph&lt;/code&gt; with labels, rotated but without the labels themselves being rotated. We can simply convert the &lt;code&gt;Tgraph&lt;/code&gt; to a &lt;code&gt;VPatch&lt;/code&gt;, and rotate that before drawing with labels.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;someAngle&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;makeVP&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also align a &lt;code&gt;VPatch&lt;/code&gt; using vertex labels.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;alignXaxis&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So if &lt;code&gt;g&lt;/code&gt; is a &lt;code&gt;Tgraph&lt;/code&gt; with vertex labels &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; we can align it on the x-axis with &lt;code&gt;a&lt;/code&gt; at the origin and &lt;code&gt;b&lt;/code&gt; on the positive x-axis (after converting to a &lt;code&gt;VPatch&lt;/code&gt;), instead of accepting the default orientation.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;alignXaxis&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;makeVP&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another use of &lt;code&gt;VPatch&lt;/code&gt;es is to share the vertex location map when drawing only subsets of the faces (see &lt;em&gt;Overlaid examples&lt;/em&gt; in the next section).&lt;/p&gt;
&lt;p&gt;&lt;a name="4"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="drawing-in-more-detail"&gt;4. Drawing in More Detail&lt;/h2&gt;
&lt;h3 id="class-drawable"&gt;Class Drawable&lt;/h3&gt;
&lt;p&gt;There is a class &lt;code&gt;Drawable&lt;/code&gt; with instances &lt;code&gt;Tgraph&lt;/code&gt;, &lt;code&gt;VPatch&lt;/code&gt;, &lt;code&gt;Patch&lt;/code&gt;. When the token &lt;code&gt;B&lt;/code&gt; is in scope standing for a fixed backend then we can assume&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;draw&lt;/span&gt;   &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;  &lt;span style="color: green;"&gt;-- draws non-join edges&lt;/span&gt;
    &lt;span&gt;drawj&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;  &lt;span style="color: green;"&gt;-- as with draw but also draws dashed join edges&lt;/span&gt;
    &lt;span&gt;fillDK&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt; &lt;span style="color: green;"&gt;-- fills with colours&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;fillDK clr1 clr2&lt;/code&gt; will fill darts with colour &lt;code&gt;clr1&lt;/code&gt; and kites with colour &lt;code&gt;clr2&lt;/code&gt; as well as drawing non-join edges.&lt;/p&gt;
&lt;p&gt;These are the main drawing tools. However they are actually defined for any suitable backend &lt;code&gt;b&lt;/code&gt; so have more general types.&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Update Sept 2024&lt;/em&gt;) From version 1.1 onwards of PenroseKiteDart, these are&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;draw&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt;   &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;OKBackend&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt;
              &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;
    &lt;span&gt;drawj&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt;  &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;OKBackend&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt;
              &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;
    &lt;span&gt;fillDK&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;OKBackend&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt;
              &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the class &lt;code&gt;OKBackend&lt;/code&gt; is a check to ensure a backend is suitable for drawing 2D tilings with or without labels.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In these notes we will generally use the simpler description of types using &lt;code&gt;B&lt;/code&gt; for a fixed chosen backend for the sake of clarity.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The drawing tools are each defined via the class function &lt;code&gt;drawWith&lt;/code&gt; using &lt;code&gt;Piece&lt;/code&gt; drawing functions.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;class&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: blue; font-weight: bold;"&gt;where&lt;/span&gt;
        &lt;span&gt;drawWith&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Piece&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    
    &lt;span&gt;draw&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;drawPiece&lt;/span&gt;
    &lt;span&gt;drawj&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;drawjPiece&lt;/span&gt;
    &lt;span&gt;fillDK&lt;/span&gt; &lt;span&gt;clr1&lt;/span&gt; &lt;span&gt;clr2&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;fillPieceDK&lt;/span&gt; &lt;span&gt;clr1&lt;/span&gt; &lt;span&gt;clr2&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To design a new drawing function, you only need to implement a function to draw a &lt;code&gt;Piece&lt;/code&gt;, (let us call it &lt;code&gt;newPieceDraw&lt;/code&gt;)&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;newPieceDraw&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can then be elevated to draw any &lt;code&gt;Drawable&lt;/code&gt; (including &lt;code&gt;Tgraph&lt;/code&gt;s, &lt;code&gt;VPatch&lt;/code&gt;es, and &lt;code&gt;Patch&lt;/code&gt;es) by applying the &lt;code&gt;Drawable&lt;/code&gt; class function &lt;code&gt;drawWith&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;newDraw&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;newDraw&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;newPieceDraw&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="class-drawablelabelled"&gt;Class DrawableLabelled&lt;/h3&gt;
&lt;p&gt;Class &lt;code&gt;DrawableLabelled&lt;/code&gt; is defined with instances &lt;code&gt;Tgraph&lt;/code&gt; and &lt;code&gt;VPatch&lt;/code&gt;, but &lt;code&gt;Patch&lt;/code&gt; is not an instance (because this does not retain vertex label information).&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;class&lt;/span&gt; &lt;span&gt;DrawableLabelled&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: blue; font-weight: bold;"&gt;where&lt;/span&gt;
        &lt;span&gt;labelColourSize&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Measure&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Patch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;labelColourSize c m&lt;/code&gt; modifies a &lt;code&gt;Patch&lt;/code&gt; drawing function to add labels (of colour &lt;code&gt;c&lt;/code&gt; and size measure &lt;code&gt;m&lt;/code&gt;). &lt;code&gt;Measure&lt;/code&gt; is defined in Diagrams.Prelude with pre-defined measures &lt;code&gt;tiny&lt;/code&gt;, &lt;code&gt;verySmall&lt;/code&gt;, &lt;code&gt;small&lt;/code&gt;, &lt;code&gt;normal&lt;/code&gt;, &lt;code&gt;large&lt;/code&gt;, &lt;code&gt;veryLarge&lt;/code&gt;, &lt;code&gt;huge&lt;/code&gt;. For most of our diagrams of &lt;code&gt;Tgraph&lt;/code&gt;s, we use red labels and we also find &lt;code&gt;small&lt;/code&gt; is a good default size choice, so we define&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;labelSize&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;DrawableLabelled&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Measure&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Patch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;labelSize&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;labelColourSize&lt;/span&gt; &lt;span&gt;red&lt;/span&gt;

    &lt;span&gt;labelled&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;DrawableLabelled&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Patch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;labelled&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;labelSize&lt;/span&gt; &lt;span&gt;small&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then &lt;code&gt;labelled draw&lt;/code&gt;, &lt;code&gt;labelled drawj&lt;/code&gt;, &lt;code&gt;labelled (fillDK clr1 clr2)&lt;/code&gt; can all be used on both &lt;code&gt;Tgraph&lt;/code&gt;s and &lt;code&gt;VPatch&lt;/code&gt;es as well as (for example) &lt;code&gt;labelSize tiny draw&lt;/code&gt;, or &lt;code&gt;labelCoulourSize blue normal drawj&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="further-drawing-functions"&gt;Further drawing functions&lt;/h3&gt;
&lt;p&gt;There are a few extra drawing functions built on top of the above ones. The function &lt;code&gt;smart&lt;/code&gt; is a modifier to add dashed join edges only when they occur on the boundary of a &lt;code&gt;Tgraph&lt;/code&gt;&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;smart&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;smart vpdraw g&lt;/code&gt; will draw dashed join edges on the boundary of &lt;code&gt;g&lt;/code&gt; before applying the drawing function &lt;code&gt;vpdraw&lt;/code&gt; to the &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;g&lt;/code&gt;. For example the following all draw dashed join edges only on the boundary for a &lt;code&gt;Tgraph g&lt;/code&gt;&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;smart&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;smart&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelSize&lt;/span&gt; &lt;span&gt;normal&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When using labels, the function &lt;code&gt;rotating&lt;/code&gt; allows a &lt;code&gt;Tgraph&lt;/code&gt; to be drawn rotated without rotating the labels.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;rotating&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Angle&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;rotating&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;makeVP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So for example,&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;rotating&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;90&lt;/span&gt;&lt;span&gt;@@&lt;/span&gt;&lt;span&gt;deg&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;makes sense for a &lt;code&gt;Tgraph g&lt;/code&gt;. Of course if there are no labels we can simply use&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;rotate&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span class="hs-num"&gt;90&lt;/span&gt;&lt;span&gt;@@&lt;/span&gt;&lt;span&gt;deg&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;draw&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly &lt;code&gt;aligning&lt;/code&gt; allows a &lt;code&gt;Tgraph&lt;/code&gt; to be aligned on the X-axis using a pair of vertex numbers before drawing.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;aligning&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;aligning&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;alignXaxis&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;makeVP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, for example, if &lt;code&gt;Tgraph g&lt;/code&gt; has vertices &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, both&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;aligning&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;aligning&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;make sense. Note that the following two examples are &lt;strong&gt;wrong&lt;/strong&gt;. Even though they type check, they re-orient &lt;code&gt;g&lt;/code&gt; without repositioning the boundary joins.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;smart&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;      &lt;span style="color: green;"&gt;-- WRONG&lt;/span&gt;
    &lt;span&gt;smart&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;alignXaxis&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;  &lt;span style="color: green;"&gt;-- WRONG&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead use&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;smartRotating&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;smartAligning&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;smartRotatinge&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Angle&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;smartAligning&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;are defined using&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;smartOn&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;smartOn g vpdraw vp&lt;/code&gt; uses the given &lt;code&gt;vp&lt;/code&gt; for drawing boundary joins and drawing faces of &lt;code&gt;g&lt;/code&gt; (with &lt;code&gt;vpdraw&lt;/code&gt;) rather than converting &lt;code&gt;g&lt;/code&gt; to a new &lt;code&gt;VPatch&lt;/code&gt;. This assumes &lt;code&gt;vp&lt;/code&gt; has locations for vertices in &lt;code&gt;g&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="overlaid-examples-location-map-sharing"&gt;Overlaid examples (location map sharing)&lt;/h3&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;drawForce&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will (smart) draw a &lt;code&gt;Tgraph g&lt;/code&gt; in red overlaid (using &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;) on the result of &lt;code&gt;force g&lt;/code&gt; as in figure 6. Similarly&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;drawPCompose&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;applied to a &lt;code&gt;Tgraph g&lt;/code&gt; will draw the result of a partial composition of &lt;code&gt;g&lt;/code&gt; as in figure 7. That is a drawing of &lt;code&gt;compose g&lt;/code&gt; but overlaid with a drawing of the remainder faces of &lt;code&gt;g&lt;/code&gt; shown in pale green.&lt;/p&gt;
&lt;p&gt;Both these functions make use of sharing a vertex location map to get correct alignments of overlaid diagrams. In the case of &lt;code&gt;drawForce g&lt;/code&gt;, we know that a &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;force g&lt;/code&gt; will contain all the vertex locations for &lt;code&gt;g&lt;/code&gt; since force only adds to a &lt;code&gt;Tgraph&lt;/code&gt; (when it succeeds). So when constructing the diagram for &lt;code&gt;g&lt;/code&gt; we can use the &lt;code&gt;VPatch&lt;/code&gt; created for &lt;code&gt;force g&lt;/code&gt; instead of starting afresh. Similarly for &lt;code&gt;drawPCompose g&lt;/code&gt; the &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;g&lt;/code&gt; contains locations for all the vertices of &lt;code&gt;compose g&lt;/code&gt; so &lt;code&gt;compose g&lt;/code&gt; is drawn using the &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;g&lt;/code&gt; instead of starting afresh.&lt;/p&gt;
&lt;p&gt;The location map sharing is done with&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;subFaces&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; 
                &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so that &lt;code&gt;subFaces fcs vp&lt;/code&gt; is a &lt;code&gt;VPatch&lt;/code&gt; with the same vertex locations as &lt;code&gt;vp&lt;/code&gt;, but replacing the faces of &lt;code&gt;vp&lt;/code&gt; with &lt;code&gt;fcs&lt;/code&gt;. [Of course, this can go wrong if the new faces have vertices not in the domain of the vertex location map so this needs to be used with care. Any errors would only be discovered when a diagram is created.]&lt;/p&gt;
&lt;p&gt;For cases where labels are only going to be drawn for certain faces, we need a version of &lt;code&gt;subFaces&lt;/code&gt; which also gets rid of vertex locations that are not relevant to the faces. For this situation we have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;restrictTo&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; 
                 &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which filters out un-needed vertex locations from the vertex location map. Unlike &lt;code&gt;subFaces&lt;/code&gt;, &lt;code&gt;restrictTo&lt;/code&gt; checks for missing vertex locations, so &lt;code&gt;restrictTo fcs vp&lt;/code&gt; raises an error if a vertex in &lt;code&gt;fcs&lt;/code&gt; is missing from the keys of the vertex location map of &lt;code&gt;vp&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a name="5"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="forcing-in-more-detail"&gt;5. Forcing in More Detail&lt;/h2&gt;
&lt;h3 id="the-force-rules"&gt;The force rules&lt;/h3&gt;
&lt;p&gt;The rules used by our force algorithm are local and derived from the fact that there are seven possible vertex types as depicted in figure 8.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 8: Seven vertex types" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/verttypesfig.png?w=625" /&gt;&lt;figcaption&gt;Figure 8: Seven vertex types&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Our rules are shown in figure 9 (omitting mirror symmetric versions). In each case the &lt;code&gt;TileFace&lt;/code&gt; shown yellow needs to be added in the presence of the other &lt;code&gt;TileFace&lt;/code&gt;s shown.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 9: Rules for forcing" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/forcerules.png?w=625" /&gt;&lt;figcaption&gt;Figure 9: Rules for forcing&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3 id="main-forcing-operations"&gt;Main Forcing Operations&lt;/h3&gt;
&lt;p&gt;To make forcing efficient we convert a &lt;code&gt;Tgraph&lt;/code&gt; to a &lt;code&gt;BoundaryState&lt;/code&gt; to keep track of boundary information of the &lt;code&gt;Tgraph&lt;/code&gt;, and then calculate a &lt;code&gt;ForceState&lt;/code&gt; which combines the &lt;code&gt;BoundaryState&lt;/code&gt; with a record of awaiting boundary edge updates (an update map). Then each face addition is carried out on a &lt;code&gt;ForceState&lt;/code&gt;, converting back when all the face additions are complete. It makes sense to apply &lt;code&gt;force&lt;/code&gt; (and related functions) to a &lt;code&gt;Tgraph&lt;/code&gt;, a &lt;code&gt;BoundaryState&lt;/code&gt;, or a &lt;code&gt;ForceState&lt;/code&gt;, so we define a class &lt;code&gt;Forcible&lt;/code&gt; with instances &lt;code&gt;Tgraph&lt;/code&gt;, &lt;code&gt;BoundaryState&lt;/code&gt;, and &lt;code&gt;ForceState&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This allows us to define&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryForce&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first will raise an error if a stuck tiling is encountered. The second uses a &lt;code&gt;Try&lt;/code&gt; result which produces a &lt;code&gt;Left string&lt;/code&gt; for failures and a &lt;code&gt;Right a&lt;/code&gt; for successful result &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are several other operations related to forcing including&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;stepForce&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryStepForce&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;

    &lt;span&gt;addHalfDart&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;addHalfKite&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryAddHalfDart&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;tryAddHalfKite&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first two force (up to) a given number of steps (=face additions) and the other four add a half dart/kite on a given boundary edge.&lt;/p&gt;
&lt;h3 id="update-generators"&gt;Update Generators&lt;/h3&gt;
&lt;p&gt;An update generator is used to calculate which boundary edges can have a certain update. There is an update generator for each force rule, but also a combined (all update) generator. The force operations mentioned above all use the default all update generator (&lt;code&gt;defaultAllUGen&lt;/code&gt;) but there are more general (&lt;em&gt;with&lt;/em&gt;) versions that can be passed an update generator of choice. For example&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;forceWith&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryForceWith&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact we defined&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;forceWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;
    &lt;span&gt;tryForce&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;tryForceWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also define&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;wholeTiles&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;wholeTiles&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;forceWith&lt;/span&gt; &lt;span&gt;wholeTileUpdates&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;wholeTileUpdates&lt;/code&gt; is an update generator that just finds boundary join edges to complete whole tiles.&lt;/p&gt;
&lt;p&gt;In addition to &lt;code&gt;defaultAllUGen&lt;/code&gt; there is also &lt;code&gt;allUGenerator&lt;/code&gt; which does the same thing apart from how failures are reported. The reason for keeping both is that they were constructed differently and so are useful for testing.&lt;/p&gt;
&lt;p&gt;In fact &lt;code&gt;UpdateGenerator&lt;/code&gt;s are functions that take a &lt;code&gt;BoundaryState&lt;/code&gt; and a focus (list of boundary directed edges) to produce an update map. Each &lt;code&gt;Update&lt;/code&gt; is calculated as either a &lt;code&gt;SafeUpdate&lt;/code&gt; (where two of the new face edges are on the existing boundary and no new vertex is needed) or an &lt;code&gt;UnsafeUpdate&lt;/code&gt; (where only one edge of the new face is on the boundary and a new vertex needs to be created for a new face).&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;BoundaryState&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;UpdateMap&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;type&lt;/span&gt; &lt;span&gt;UpdateMap&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;Map.Map&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;Update&lt;/span&gt;
    &lt;span style="color: blue; font-weight: bold;"&gt;data&lt;/span&gt; &lt;span&gt;Update&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;SafeUpdate&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; 
                &lt;span style="color: red;"&gt;|&lt;/span&gt; &lt;span&gt;UnsafeUpdate&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Completing (executing) an &lt;code&gt;UnsafeUpdate&lt;/code&gt; requires a touching vertex check to ensure that the new vertex does not clash with an existing boundary vertex. Using an existing (touching) vertex would create a crossing boundary so such an update has to be blocked.&lt;/p&gt;
&lt;h3 id="forcible-class-operations"&gt;Forcible Class Operations&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Forcible&lt;/code&gt; class operations are higher order and designed to allow for easy additions of further generic operations. They take care of conversions between &lt;code&gt;Tgraph&lt;/code&gt;s, &lt;code&gt;BoundaryState&lt;/code&gt;s and &lt;code&gt;ForceState&lt;/code&gt;s.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;class&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: blue; font-weight: bold;"&gt;where&lt;/span&gt;
      &lt;span&gt;tryFSOpWith&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;ForceState&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
      &lt;span&gt;tryChangeBoundaryWith&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;BoundaryState&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;BoundaryChange&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
      &lt;span&gt;tryInitFSWith&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, given an update generator &lt;code&gt;ugen&lt;/code&gt; and any &lt;code&gt;f:: ForceState -&amp;gt; Try ForceState&lt;/code&gt; , then &lt;code&gt;f&lt;/code&gt; can be generalised to work on any &lt;code&gt;Forcible&lt;/code&gt; using &lt;code&gt;tryFSOpWith ugen f&lt;/code&gt;. This is used to define both &lt;code&gt;tryForceWith&lt;/code&gt; and &lt;code&gt;tryStepForceWith&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We also specialize &lt;code&gt;tryFSOpWith&lt;/code&gt; to use the default update generator&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryFSOp&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;ForceState&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryFSOp&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;tryFSOpWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly given an update generator &lt;code&gt;ugen&lt;/code&gt; and any &lt;code&gt;f:: BoundaryState -&amp;gt; Try BoundaryChange&lt;/code&gt; , then &lt;code&gt;f&lt;/code&gt; can be generalised to work on any &lt;code&gt;Forcible&lt;/code&gt; using &lt;code&gt;tryChangeBoundaryWith ugen f&lt;/code&gt;. This is used to define &lt;code&gt;tryAddHalfDart&lt;/code&gt; and &lt;code&gt;tryAddHalfKite&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We also specialize &lt;code&gt;tryChangeBoundaryWith&lt;/code&gt; to use the default update generator&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryChangeBoundary&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;BoundaryState&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;BoundaryChange&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryChangeBoundary&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;tryChangeBoundaryWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the type &lt;code&gt;BoundaryChange&lt;/code&gt; contains a resulting &lt;code&gt;BoundaryState&lt;/code&gt;, the single &lt;code&gt;TileFace&lt;/code&gt; that has been added, a list of edges removed from the boundary (of the &lt;code&gt;BoundaryState&lt;/code&gt; prior to the face addition), and a list of the (3 or 4) boundary edges affected around the change that require checking or re-checking for updates.&lt;/p&gt;
&lt;p&gt;The class function &lt;code&gt;tryInitFSWith&lt;/code&gt; will use an update generator to create an initial &lt;code&gt;ForceState&lt;/code&gt; for any &lt;code&gt;Forcible&lt;/code&gt;. If the &lt;code&gt;Forcible&lt;/code&gt; is already a &lt;code&gt;ForceState&lt;/code&gt; it will do nothing. Otherwise it will calculate updates for the whole boundary. We also have the special case&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryInitFS&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;
    &lt;span&gt;tryInitFS&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;tryInitFSWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="efficient-chains-of-forcing-operations."&gt;Efficient chains of forcing operations.&lt;/h3&gt;
&lt;p&gt;Note that &lt;code&gt;(force . force)&lt;/code&gt; does the same as &lt;code&gt;force&lt;/code&gt;, but we might want to chain other &lt;code&gt;force&lt;/code&gt; related steps in a calculation.&lt;/p&gt;
&lt;p&gt;For example, consider the following combination which, after decomposing a &lt;code&gt;Tgraph&lt;/code&gt;, forces, then adds a half dart on a given boundary edge (&lt;code&gt;d&lt;/code&gt;) and then forces again.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;combo&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;force&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;addHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;force&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;code&gt;decompose:: Tgraph -&amp;gt; Tgraph&lt;/code&gt;, the instances of &lt;code&gt;force&lt;/code&gt; and &lt;code&gt;addHalfDart d&lt;/code&gt; will have type &lt;code&gt;Tgraph -&amp;gt; Tgraph&lt;/code&gt; so each of these operations, will begin and end with conversions between &lt;code&gt;Tgraph&lt;/code&gt; and &lt;code&gt;ForceState&lt;/code&gt;. We would do better to avoid these wasted intermediate conversions working only with &lt;code&gt;ForceState&lt;/code&gt;s and keeping only those necessary conversions at the beginning and end of the whole sequence.&lt;/p&gt;
&lt;p&gt;This can be done using &lt;code&gt;tryFSOp&lt;/code&gt;. To see this, let us first re-express the forcing sequence using the &lt;code&gt;Try&lt;/code&gt; monad, so&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;addHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;force&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;becomes&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryAddHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that (&lt;code&gt;&amp;lt;=&amp;lt;&lt;/code&gt;) is the Kliesli arrow which replaces composition for Monads (defined in Control.Monad). (We could also have expressed this right to left sequence with a left to right version &lt;code&gt;tryForce &amp;gt;=&amp;gt; tryAddHalfDart d &amp;gt;=&amp;gt; tryForce&lt;/code&gt;). The definition of &lt;code&gt;combo&lt;/code&gt; becomes&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;combo&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryAddHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has no performance improvement, but now we can pass the sequence to &lt;code&gt;tryFSOp&lt;/code&gt; to remove the unnecessary conversions between steps.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;combo&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;tryFSOp&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryAddHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sequence actually has type &lt;code&gt;Forcible a =&amp;gt; a -&amp;gt; Try a&lt;/code&gt; but when passed to &lt;code&gt;tryFSOp&lt;/code&gt; it specialises to type &lt;code&gt;ForceState -&amp;gt; Try ForseState&lt;/code&gt;. This ensures the sequence works on a &lt;code&gt;ForceState&lt;/code&gt; and any conversions are confined to the beginning and end of the sequence, avoiding unnecessary intermediate conversions.&lt;/p&gt;
&lt;h3 id="a-limitation-of-forcing"&gt;A limitation of forcing&lt;/h3&gt;
&lt;p&gt;To avoid creating touching vertices (or crossing boundaries) a &lt;code&gt;BoundaryState&lt;/code&gt; keeps track of locations of boundary vertices. At around 35,000 face additions in a single &lt;code&gt;force&lt;/code&gt; operation the calculated positions of boundary vertices can become too inaccurate to prevent touching vertex problems. In such cases it is better to use&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;recalibratingForce&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryRecalibratingForce&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These work by recalculating all vertex positions at 20,000 step intervals to get more accurate boundary vertex positions. For example, 6 decompositions of the &lt;code&gt;kingGraph&lt;/code&gt; has 2,906 faces. Applying &lt;code&gt;force&lt;/code&gt; to this should result in 53,574 faces but will go wrong before it reaches that. This can be fixed by calculating either&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;recalibratingForce&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;decompositions&lt;/span&gt; &lt;span&gt;kingGraph&lt;/span&gt; &lt;span&gt;!!&lt;/span&gt;&lt;span class="hs-num"&gt;6&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or using an extra &lt;code&gt;force&lt;/code&gt; before the decompositions&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;decompositions&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;force&lt;/span&gt; &lt;span&gt;kingGraph&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span&gt;!!&lt;/span&gt;&lt;span class="hs-num"&gt;6&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the latter case, the final &lt;code&gt;force&lt;/code&gt; only needs to add 17,864 faces to the 35,710 produced by &lt;code&gt;decompositions (force kingGraph) !!6&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a name="6"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="advanced-operations"&gt;6. Advanced Operations&lt;/h2&gt;
&lt;h3 id="guided-comparison-of-tgraphs"&gt;Guided comparison of &lt;code&gt;Tgraph&lt;/code&gt;s&lt;/h3&gt;
&lt;p&gt;Asking if two &lt;code&gt;Tgraph&lt;/code&gt;s are equivalent (the same apart from choice of vertex numbers) is a an np-complete problem. However, we do have an efficient &lt;em&gt;guided&lt;/em&gt; way of comparing &lt;code&gt;Tgraph&lt;/code&gt;s. In the module &lt;code&gt;Tgraph.Rellabelling&lt;/code&gt; we have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;sameGraph&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The expression &lt;code&gt;sameGraph (g1,d1) (g2,d2)&lt;/code&gt; asks if &lt;code&gt;g2&lt;/code&gt; can be relabelled to match &lt;code&gt;g1&lt;/code&gt; assuming that the directed edge &lt;code&gt;d2&lt;/code&gt; in &lt;code&gt;g2&lt;/code&gt; is identified with &lt;code&gt;d1&lt;/code&gt; in &lt;code&gt;g1&lt;/code&gt;. Hence the comparison is guided by the assumption that &lt;code&gt;d2&lt;/code&gt; corresponds to &lt;code&gt;d1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is implemented using&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryRelabelToMatch&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;tryRelabelToMatch (g1,d1) (g2,d2)&lt;/code&gt; will either fail with a &lt;code&gt;Left report&lt;/code&gt; if a mismatch is found when relabelling &lt;code&gt;g2&lt;/code&gt; to match &lt;code&gt;g1&lt;/code&gt; or will succeed with &lt;code&gt;Right g3&lt;/code&gt; where &lt;code&gt;g3&lt;/code&gt; is a relabelled version of &lt;code&gt;g2&lt;/code&gt;. The successful result &lt;code&gt;g3&lt;/code&gt; will match &lt;code&gt;g1&lt;/code&gt; in a maximal tile-connected collection of faces containing the face with edge &lt;code&gt;d1&lt;/code&gt; and have vertices disjoint from those of &lt;code&gt;g1&lt;/code&gt; elsewhere. The comparison tries to grow a suitable relabelling by comparing faces one at a time starting from the face with edge &lt;code&gt;d1&lt;/code&gt; in &lt;code&gt;g1&lt;/code&gt; and the face with edge &lt;code&gt;d2&lt;/code&gt; in &lt;code&gt;g2&lt;/code&gt;. (This relies on the fact that &lt;code&gt;Tgraph&lt;/code&gt;s are connected with no crossing boundaries, and hence tile-connected.)&lt;/p&gt;
&lt;p&gt;The above function is also used to implement&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;tryFullUnion&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which tries to find the union of two &lt;code&gt;Tgraph&lt;/code&gt;s guided by a directed edge identification. However, there is an extra complexity arising from the fact that &lt;code&gt;Tgraph&lt;/code&gt;s might &lt;em&gt;overlap&lt;/em&gt; in more than one tile-connected region. After calculating one overlapping region, the full union uses some geometry (calculating vertex locations) to detect further overlaps.&lt;/p&gt;
&lt;p&gt;Finally we have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;commonFaces&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will find common regions of overlapping faces of two &lt;code&gt;Tgraph&lt;/code&gt;s guided by a directed edge identification. The resulting common faces will be a sub-collection of faces from the first &lt;code&gt;Tgraph&lt;/code&gt;. These are returned as a list as they may not be a connected collection of faces and therefore not necessarily a &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id="empires-and-superforce"&gt;Empires and SuperForce&lt;/h3&gt;
&lt;p&gt;In &lt;a href="https://readerunner.wordpress.com/2023/04/26/graphs-kites-and-darts-empires-and-superforce/"&gt;Empires and SuperForce&lt;/a&gt; we discussed forced boundary coverings which were used to implement both a &lt;code&gt;superForce&lt;/code&gt; operation&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;superForce&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and operations to calculate empires.&lt;/p&gt;
&lt;p&gt;We will not repeat the descriptions here other than to note that&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;forcedBoundaryECovering&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;finds boundary edge coverings after forcing a &lt;code&gt;Tgraph&lt;/code&gt;. That is, &lt;code&gt;forcedBoundaryECovering g&lt;/code&gt; will first force &lt;code&gt;g&lt;/code&gt;, then (if it succeeds) finds a collection of (forced) extensions to &lt;code&gt;force g&lt;/code&gt; such that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;each extension has the whole boundary of &lt;code&gt;force g&lt;/code&gt; as internal edges.&lt;/li&gt;
&lt;li&gt;each possible addition to a boundary edge of &lt;code&gt;force g&lt;/code&gt; (kite or dart) has been included in the collection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(&lt;em&gt;possible&lt;/em&gt; here means – not leading to a stuck &lt;code&gt;Tgraph&lt;/code&gt; when forced.) There is also&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;forcedBoundaryVCovering&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which does the same except that the extensions have all boundary vertices internal rather than just the boundary edges. In both cases the result is a list of explicitly forced Tgraphs (discussed next).&lt;/p&gt;
&lt;h3 id="combinations-and-explicitly-forced"&gt;Combinations and Explicitly Forced&lt;/h3&gt;
&lt;p&gt;We introduced a new type &lt;code&gt;Forced&lt;/code&gt; (in v 1.3) to enable a forcible to be explictily labelled as being forced. For example&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;forceF&lt;/span&gt;    &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; 
    &lt;span&gt;tryForceF&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span style="color: red;"&gt;(&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span style="color: red;"&gt;)&lt;/span&gt;
    &lt;span&gt;forgetF&lt;/span&gt;   &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows us to restrict certain functions which expect a forced argument by making this explicit.&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;composeF&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition makes use of theorems established in &lt;a href="https://readerunner.wordpress.com/2023/09/12/graphs-kites-and-darts-and-theorems/"&gt;Graphs,Kites and Darts and Theorems&lt;/a&gt; that composing a forced &lt;code&gt;Tgraph&lt;/code&gt; does not require a check (for connectedness and no crossing boundaries) and the result is also forced. This can then be used to define efficient combinations such as&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;compForce&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;      &lt;span style="color: green;"&gt;-- compose after forcing&lt;/span&gt;
    &lt;span&gt;compForce&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;composeF&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;forceF&lt;/span&gt;

    &lt;span&gt;allCompForce&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; &lt;span style="color: green;"&gt;-- iterated (compose after force) while not emptyTgraph&lt;/span&gt;
    &lt;span&gt;maxCompForce&lt;/span&gt;&lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;   &lt;span style="color: green;"&gt;-- last item in allCompForce (or emptyTgraph)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="tracked-tgraphs"&gt;Tracked Tgraphs&lt;/h3&gt;
&lt;p&gt;The type&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span style="color: blue; font-weight: bold;"&gt;data&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;=&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt;
       &lt;span style="color: red;"&gt;{&lt;/span&gt; &lt;span&gt;tgraph&lt;/span&gt;  &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
       &lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;tracked&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; 
       &lt;span style="color: red;"&gt;}&lt;/span&gt; &lt;span style="color: blue; font-weight: bold;"&gt;deriving&lt;/span&gt; &lt;span&gt;Show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has proven useful in experimentation as well as in producing artwork with darts and kites. The idea is to keep a record of sub-collections of faces of a &lt;code&gt;Tgraph&lt;/code&gt; when doing both force operations and decompositions. A list of the sub-collections forms the tracked list associated with the &lt;code&gt;Tgraph&lt;/code&gt;. We make &lt;code&gt;TrackedTgraph&lt;/code&gt; an instance of class &lt;code&gt;Forcible&lt;/code&gt; by having force operations only affect the &lt;code&gt;Tgraph&lt;/code&gt; and not the tracked list. The significant idea is the implementation of&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;decomposeTracked&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Decomposition of a &lt;code&gt;Tgraph&lt;/code&gt; involves introducing a new vertex for each long edge and each kite join. These are then used to construct the decomposed faces. For &lt;code&gt;decomposeTracked&lt;/code&gt; we do the same for the &lt;code&gt;Tgraph&lt;/code&gt;, but when it comes to the tracked collections, we decompose them re-using the same new vertex numbers calculated for the edges in the &lt;code&gt;Tgraph&lt;/code&gt;. This keeps a consistent numbering between the &lt;code&gt;Tgraph&lt;/code&gt; and tracked faces, so each item in the tracked list remains a sub-collection of faces in the &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;drawTrackedTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span style="color: red;"&gt;[&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span style="color: red;"&gt;]&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is used to draw a &lt;code&gt;TrackedTgraph&lt;/code&gt;. It uses a list of functions to draw &lt;code&gt;VPatch&lt;/code&gt;es. The first drawing function is applied to a &lt;code&gt;VPatch&lt;/code&gt; for any untracked faces. Subsequent functions are applied to &lt;code&gt;VPatch&lt;/code&gt;es for the tracked list in order. Each diagram is beneath later ones in the list, with the diagram for the untracked faces at the bottom. The &lt;code&gt;VPatch&lt;/code&gt;es used are all restrictions of a single &lt;code&gt;VPatch&lt;/code&gt; for the &lt;code&gt;Tgraph&lt;/code&gt;, so will be consistent in vertex locations. When labels are used, there is also a &lt;code&gt;drawTrackedTgraphRotating&lt;/code&gt; and &lt;code&gt;drawTrackedTgraphAligning&lt;/code&gt; for rotating or aligning the &lt;code&gt;VPatch&lt;/code&gt; prior to applying the drawing functions.&lt;/p&gt;
&lt;p&gt;Note that the result of calculating empires (see &lt;a href="https://readerunner.wordpress.com/2023/04/26/graphs-kites-and-darts-empires-and-superforce/"&gt;Empires and SuperForce&lt;/a&gt; ) is represented as a &lt;code&gt;TrackedTgraph&lt;/code&gt;. The result is actually the common faces of a forced boundary covering, but a particular element of the covering (the first one) is chosen as the background &lt;code&gt;Tgraph&lt;/code&gt; with the common faces as a tracked sub-collection of faces. Hence we have&lt;/p&gt;
&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;    &lt;span&gt;empire1&lt;/span&gt;&lt;span style="color: red;"&gt;,&lt;/span&gt; &lt;span&gt;empire2&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt;
    
    &lt;span&gt;drawEmpire&lt;/span&gt; &lt;span style="color: red;"&gt;::&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span style="color: red;"&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Figure 10 was also created using &lt;code&gt;TrackedTgraph&lt;/code&gt;s.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Figure 10: Using a TrackedTgraph for drawing" src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/cover.png?w=625" /&gt;&lt;figcaption&gt;Figure 10: Using a TrackedTgraph for drawing&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a name="7"&gt; &lt;/a&gt;&lt;/p&gt;
&lt;h2 id="other-reading"&gt;7. Other Reading&lt;/h2&gt;
&lt;p&gt;Previous related blogs are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2021/03/20/diagrams-for-penrose-tiles/"&gt;Diagrams for Penrose Tiles&lt;/a&gt; – the first blog introduced drawing &lt;code&gt;Piece&lt;/code&gt;s and &lt;code&gt;Patch&lt;/code&gt;es (without using Tgraphs) and provided a version of decomposing for Patches (&lt;code&gt;decompPatch&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2022/01/06/graphs-kites-and-darts/"&gt;Graphs, Kites and Darts&lt;/a&gt; intoduced Tgraphs. This gave more details of implementation and results of early explorations. (The class &lt;code&gt;Forcible&lt;/code&gt; was introduced subsequently).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2023/04/26/graphs-kites-and-darts-empires-and-superforce/"&gt;Empires and SuperForce&lt;/a&gt; – these new operations were based on observing properties of boundaries of forced Tgraphs.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2023/09/12/graphs-kites-and-darts-and-theorems/"&gt;Graphs,Kites and Darts and Theorems&lt;/a&gt; established some important results relating &lt;code&gt;force&lt;/code&gt;, &lt;code&gt;compose&lt;/code&gt;, &lt;code&gt;decompose&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;</description><pubDate>Fri, 27 Feb 2026 13:25:56 +0000</pubDate><ns0:encoded xmlns:ns0="http://purl.org/rss/1.0/modules/content/">&lt;div class="entry-content" morss_own_score="5.807566557683325" morss_score="797.2933123861453"&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;(Updated February 2026 for PenroseKiteDart version 1.6.1)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PenroseKiteDart is a Haskell package with tools to experiment with finite tilings of Penrose’s Kites and Darts. It uses the &lt;a href="https://diagrams.github.io"&gt;Haskell Diagrams&lt;/a&gt; package for drawing tilings. As well as providing drawing tools, this package introduces tile graphs (&lt;code&gt;Tgraphs&lt;/code&gt;) for describing finite tilings. (I would like to thank Stephen Huggett for suggesting planar graphs as a way to reperesent the tilings).&lt;/p&gt;
&lt;p&gt;This document summarises the design and use of the PenroseKiteDart package.&lt;/p&gt;
&lt;p&gt;PenroseKiteDart package is now available on &lt;a href="https://hackage.haskell.org"&gt;Hackage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The source files are available on GitHub at &lt;a href="https://github.com/chrisreade/PenroseKiteDart"&gt;https://github.com/chrisreade/PenroseKiteDart&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is a small art gallery of examples created with PenroseKiteDart &lt;a href="https://github.com/chrisreade/PenroseKiteDart/tree/master/ArtGallery"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Index&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;1. About Penrose’s Kites and Darts&lt;/h2&gt;
&lt;h3&gt;The Tiles&lt;/h3&gt;
&lt;p&gt;In figure 1 we show a dart and a kite. All angles are multiples of &lt;img src="https://s0.wp.com/latex.php?latex=36%5E%7B%5Ccirc%7D&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002"&gt; (a tenth of a full turn). If the shorter edges are of length 1, then the longer edges are of length &lt;img src="https://s0.wp.com/latex.php?latex=%5Cphi&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002"&gt;, where &lt;img src="https://s0.wp.com/latex.php?latex=%5Cphi+%3D+%281%2B+%5Csqrt%7B5%7D%29%2F+2&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002"&gt; is the golden ratio.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/geomtiles.png?w=625"&gt;&lt;figcaption&gt;Figure 1: The Dart and Kite Tiles&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;Aperiodic Infinite Tilings&lt;/h3&gt;
&lt;p&gt;What is interesting about these tiles is:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;It is possible to tile the entire plane with kites and darts in an aperiodic way.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Such a tiling is non-periodic and does not contain arbitrarily large periodic regions or patches.&lt;/p&gt;
&lt;p&gt;The possibility of aperiodic tilings with kites and darts was discovered by Sir Roger Penrose in 1974. There are other shapes with this property, including a chiral aperiodic monotile discovered in 2023 by Smith, Myers, Kaplan, Goodman-Strauss. (See the Penrose Tiling &lt;a href="https://en.wikipedia.org/wiki/Penrose_tiling"&gt;Wikipedia page&lt;/a&gt; for the history of aperiodic tilings)&lt;/p&gt;
&lt;p&gt;This package is entirely concerned with Penrose’s kite and dart tilings also known as P2 tilings.&lt;/p&gt;
&lt;h3&gt;Legal Tilings&lt;/h3&gt;
&lt;p&gt;In figure 2 we add a temporary green line marking purely to illustrate a rule for making &lt;em&gt;legal tilings&lt;/em&gt;. The purpose of the rule is to exclude the possibility of periodic tilings.&lt;/p&gt;
&lt;p&gt;If all tiles are marked as shown, then whenever tiles come together at a point, they must all be marked or must all be unmarked at that meeting point. So, for example, each long edge of a kite can be placed legally on only &lt;em&gt;one&lt;/em&gt; of the two long edges of a dart. The kite wing vertex (which is marked) has to go next to the dart tip vertex (which is marked) and cannot go next to the dart wing vertex (which is unmarked) for a legal tiling.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/markedtiles2.png?w=625"&gt;&lt;figcaption&gt;Figure 2: Marked Dart and Kite&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;Correct Tilings&lt;/h3&gt;
&lt;p&gt;Unfortunately, having a finite legal tiling is not enough to guarantee you can continue the tiling without getting stuck. Finite legal tilings which can be continued to cover the entire plane are called &lt;em&gt;correct&lt;/em&gt; and the others (which are doomed to get stuck) are called &lt;em&gt;incorrect&lt;/em&gt;. This means that decomposition and forcing (described later) become important tools for constructing correct finite tilings.&lt;/p&gt;
&lt;h2&gt;2. Using the PenroseKiteDart Package&lt;/h2&gt;
&lt;p&gt;You will need the Haskell Diagrams package (See &lt;a href="https://diagrams.github.io"&gt;Haskell Diagrams&lt;/a&gt;) as well as this package (PenroseKiteDart). When these are installed, you can produce diagrams with a Main.hs module. This should import a chosen backend for diagrams such as the default (SVG) along with &lt;code&gt;Diagrams.Prelude&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;module&lt;/span&gt; &lt;span&gt;Main&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;where&lt;/span&gt;
    
    &lt;span&gt;import&lt;/span&gt; &lt;span&gt;Diagrams.Backend.SVG.CmdLine&lt;/span&gt;
    &lt;span&gt;import&lt;/span&gt; &lt;span&gt;Diagrams.Prelude&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Penrose’s Kite and Dart tilings, you also need to import the &lt;code&gt;PKD&lt;/code&gt; module and (optionally) the &lt;code&gt;TgraphExamples&lt;/code&gt; module.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;import&lt;/span&gt; &lt;span&gt;PKD&lt;/span&gt;
    &lt;span&gt;import&lt;/span&gt; &lt;span&gt;TgraphExamples&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then to ouput &lt;code&gt;someExample&lt;/code&gt; figure&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;fig&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;fig&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;someExample&lt;/span&gt;

    &lt;span&gt;main&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;IO&lt;/span&gt; &lt;span&gt;()&lt;/span&gt;
    &lt;span&gt;main&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;mainWith&lt;/span&gt; &lt;span&gt;fig&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the token &lt;code&gt;B&lt;/code&gt; is used in the diagrams package to represent the chosen backend for output. So a diagram has type &lt;code&gt;Diagram B&lt;/code&gt;. In this case &lt;code&gt;B&lt;/code&gt; is bound to SVG by the import of the SVG backend. When the compiled module is executed it will generate an SVG file. (See &lt;a href="https://diagrams.github.io"&gt;Haskell Diagrams&lt;/a&gt; for more details on producing diagrams and using alternative backends).&lt;/p&gt;
&lt;h2&gt;3. Overview of Types and Operations&lt;/h2&gt;
&lt;h3&gt;Half-Tiles&lt;/h3&gt;
&lt;p&gt;In order to implement operations on tilings (&lt;code&gt;decompose&lt;/code&gt; in particular), we work with half-tiles. These are illustrated in figure 3 and labelled &lt;code&gt;RD&lt;/code&gt; (right dart), &lt;code&gt;LD&lt;/code&gt; (left dart), &lt;code&gt;LK&lt;/code&gt; (left kite), &lt;code&gt;RK&lt;/code&gt; (right kite). The &lt;em&gt;join&lt;/em&gt; edges where left and right halves come together are shown with dotted lines, leaving one short edge and one long edge on each half-tile (excluding the join edge). We have shown a red dot at the vertex we regard as the origin of each half-tile (the tip of a half-dart and the base of a half-kite).&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/newpiecesfig.png?w=625"&gt;&lt;figcaption&gt;Figure 3: Half-Tile pieces showing join edges (dashed) and origin vertices (red dots)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The labels are actually data constructors introduced with type operator &lt;code&gt;HalfTile&lt;/code&gt; which has an argument type (&lt;code&gt;rep&lt;/code&gt;) to allow for more than one representation of the half-tiles.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;data&lt;/span&gt; &lt;span&gt;HalfTile&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; 
      &lt;span&gt;=&lt;/span&gt; &lt;span&gt;LD&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span&gt;-- Left Dart&lt;/span&gt;
      &lt;span&gt;|&lt;/span&gt; &lt;span&gt;RD&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span&gt;-- Right Dart&lt;/span&gt;
      &lt;span&gt;|&lt;/span&gt; &lt;span&gt;LK&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span&gt;-- Left Kite&lt;/span&gt;
      &lt;span&gt;|&lt;/span&gt; &lt;span&gt;RK&lt;/span&gt; &lt;span&gt;rep&lt;/span&gt; &lt;span&gt;-- Right Kite&lt;/span&gt;
      &lt;span&gt;deriving&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Eq&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Tgraphs&lt;/h3&gt;
&lt;p&gt;We introduce tile graphs (&lt;code&gt;Tgraph&lt;/code&gt;s) which provide a simple planar graph representation for finite patches of tiles. For &lt;code&gt;Tgraph&lt;/code&gt;s we first specialise &lt;code&gt;HalfTile&lt;/code&gt; with a triple of vertices (positive integers) to make a &lt;code&gt;TileFace&lt;/code&gt; such as &lt;code&gt;RD(1,2,3)&lt;/code&gt;, where the vertices go clockwise round the half-tile triangle starting with the origin.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt;  &lt;span&gt;=&lt;/span&gt; &lt;span&gt;HalfTile&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt;    &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt;  &lt;span&gt;-- must be positive&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;makeTgraph&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;then constructs a &lt;code&gt;Tgraph&lt;/code&gt; from a &lt;code&gt;TileFace&lt;/code&gt; list after checking the &lt;code&gt;TileFace&lt;/code&gt;s satisfy certain properties (described below). We also have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;faces&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;to retrieve the &lt;code&gt;TileFace&lt;/code&gt; list from a &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As an example, the &lt;code&gt;fool&lt;/code&gt; (short for &lt;em&gt;fool’s kite&lt;/em&gt; and also called an &lt;em&gt;ace&lt;/em&gt; in the literature) consists of two kites and a dart (= 4 half-kites and 2 half-darts):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;fool&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;fool&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;makeTgraph&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;RD&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;LD&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;   &lt;span&gt;-- right and left dart&lt;/span&gt;
                      &lt;span&gt;,&lt;/span&gt;&lt;span&gt;LK&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;RK&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;   &lt;span&gt;-- left and right kite&lt;/span&gt;
                      &lt;span&gt;,&lt;/span&gt;&lt;span&gt;RK&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;LK&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;   &lt;span&gt;-- right and left kite&lt;/span&gt;
                      &lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To produce a diagram, we simply &lt;code&gt;draw&lt;/code&gt; the &lt;code&gt;Tgraph&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;fool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will produce the diagram on the left in figure 4.&lt;/p&gt;
&lt;p&gt;Alternatively,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;foolFigure&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;drawj&lt;/span&gt; &lt;span&gt;fool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will produce the diagram on the right in figure 4 (showing vertex labels and dashed join edges).&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/newfool.png?w=625"&gt;&lt;figcaption&gt;Figure 4: Diagram of &lt;code&gt;fool&lt;/code&gt; without labels and join edges (left), and with (right)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;When any (non-empty) &lt;code&gt;Tgraph&lt;/code&gt; is drawn, a default orientation and scale are chosen based on the lowest numbered join edge. This is aligned on the positive x-axis with length 1 (for darts) or length &lt;img src="https://s0.wp.com/latex.php?latex=%5Cphi&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002"&gt; (for kites).&lt;/p&gt;
&lt;h3&gt;Tgraph Properties&lt;/h3&gt;
&lt;p&gt;Tgraphs are actually implemented as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;newtype&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
                     &lt;span&gt;deriving&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Show&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but the data constructor &lt;code&gt;Tgraph&lt;/code&gt; is not exported to avoid accidentally by-passing checks for the required properties. The properties checked by &lt;code&gt;makeTgraph&lt;/code&gt; ensure the &lt;code&gt;Tgraph&lt;/code&gt; represents a legal tiling as a planar graph with positive vertex numbers, and that the collection of half-tile faces are both connected and have no crossing boundaries (see note below). Finally, there is a check to ensure two or more distinct vertex numbers are not used to represent the same vertex of the graph (a &lt;em&gt;touching vertex&lt;/em&gt; check). An error is raised if there is a problem.&lt;/p&gt;
&lt;p&gt;Note: If the &lt;code&gt;TileFace&lt;/code&gt;s are faces of a planar graph there will also be exterior (untiled) regions, and in graph theory these would also be called faces of the graph. To avoid confusion, we will refer to these only as &lt;em&gt;exterior regions&lt;/em&gt;, and unless otherwise stated, &lt;em&gt;face&lt;/em&gt; will mean a &lt;code&gt;TileFace&lt;/code&gt;. We can then define the boundary of a list of &lt;code&gt;TileFace&lt;/code&gt;s as the edges of the exterior regions. There is a &lt;em&gt;crossing boundary&lt;/em&gt; if the boundary crosses itself at a vertex. We exclude crossing boundaries from &lt;code&gt;Tgraph&lt;/code&gt;s because they prevent us from calculating relative positions of tiles locally and create touching vertex problems.&lt;/p&gt;
&lt;p&gt;For convenience, in addition to &lt;code&gt;makeTgraph&lt;/code&gt;, we also have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;makeUncheckedTgraph&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;checkedTgraph&lt;/span&gt;   &lt;span&gt;::&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first of these (performing no checks) is useful when you know the required properties hold. The second performs the same checks as &lt;code&gt;makeTgraph&lt;/code&gt; except that it omits the touching vertex check. This could be used, for example, when making a &lt;code&gt;Tgraph&lt;/code&gt; from a sub-collection of &lt;code&gt;TileFace&lt;/code&gt;s of another &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Main Tiling Operations&lt;/h3&gt;
&lt;p&gt;There are three key operations on finite tilings, namely&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;decompose&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;force&lt;/span&gt;     &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;compose&lt;/span&gt;   &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Decompose&lt;/h4&gt;
&lt;p&gt;Decomposition (also called &lt;em&gt;deflation&lt;/em&gt;) works by splitting each half-tile into either 2 or 3 new (&lt;em&gt;smaller scale&lt;/em&gt;) half-tiles, to produce a new tiling. The fact that this is possible, is used to establish the existence of infinite aperiodic tilings with kites and darts. Since our &lt;code&gt;Tgraph&lt;/code&gt;s have abstracted away from scale, the result of decomposing a &lt;code&gt;Tgraph&lt;/code&gt; is just another &lt;code&gt;Tgraph&lt;/code&gt;. However if we wish to compare before and after with a drawing, the latter should be scaled by a factor &lt;img src="https://s0.wp.com/latex.php?latex=1%2F%7B%5Cphi%7D+%3D+%5Cphi+-+1&amp;amp;bg=ffffff&amp;amp;fg=444444&amp;amp;s=0&amp;amp;c=20201002"&gt; times the scale of the former, to reflect the change in scale.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/foolandfoold.png?w=625"&gt;&lt;figcaption&gt;Figure 5: &lt;code&gt;fool&lt;/code&gt; (left) and &lt;code&gt;decompose fool&lt;/code&gt; (right)&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;We can, of course, iterate &lt;code&gt;decompose&lt;/code&gt; to produce an infinite list of finer and finer decompositions of a &lt;code&gt;Tgraph&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;decompositions&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
    &lt;span&gt;decompositions&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;iterate&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Force&lt;/h4&gt;
&lt;p&gt;Force works by adding any &lt;code&gt;TileFace&lt;/code&gt;s on the boundary edges of a &lt;code&gt;Tgraph&lt;/code&gt; which are &lt;em&gt;forced&lt;/em&gt;. That is, where there is only one legal choice of &lt;code&gt;TileFace&lt;/code&gt; addition consistent with the seven possible vertex types. Such additions are continued until either (i) there are no more forced cases, in which case a final (forced) &lt;code&gt;Tgraph&lt;/code&gt; is returned, or (ii) the process finds the tiling is stuck, in which case an error is raised indicating an incorrect tiling. [In the latter case, the argument to &lt;code&gt;force&lt;/code&gt; must have been an incorrect tiling, because the forced additions cannot produce an incorrect tiling starting from a correct tiling.]&lt;/p&gt;
&lt;p&gt;An example is shown in figure 6. When forced, the &lt;code&gt;Tgraph&lt;/code&gt; on the left produces the result on the right. The original is highlighted in red in the result to show what has been added.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/fooldandforce.png?w=625"&gt;&lt;figcaption&gt;Figure 6: A Tgraph (left) and its forced result (right) with the original shown red&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;Compose&lt;/h4&gt;
&lt;p&gt;Composition (also called &lt;em&gt;inflation&lt;/em&gt;) is an opposite to &lt;code&gt;decompose&lt;/code&gt; but this has complications for finite tilings, so it is not simply an inverse. (See &lt;a href="https://readerunner.wordpress.com/2023/09/12/graphs-kites-and-darts-and-theorems/"&gt;Graphs,Kites and Darts and Theorems&lt;/a&gt; for more discussion of the problems). Figure 7 shows a &lt;code&gt;Tgraph&lt;/code&gt; (left) with the result of composing (right) where we have also shown (in pale green) the faces of the original that are not included in the composition – the remainder faces.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/pcomposeexample.png?w=625"&gt;&lt;figcaption&gt;Figure 7: A Tgraph (left) and its (part) composed result (right) with the remainder faces shown pale green&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Under some circumstances composing can fail to produce a &lt;code&gt;Tgraph&lt;/code&gt; because there are crossing boundaries in the resulting &lt;code&gt;TileFaces&lt;/code&gt;. However, we have established that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;g&lt;/code&gt; is a forced &lt;code&gt;Tgraph&lt;/code&gt;, then &lt;code&gt;compose g&lt;/code&gt; is defined and it is also a forced &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Try Results&lt;/h3&gt;
&lt;p&gt;It is convenient to use types of the form &lt;code&gt;Try a&lt;/code&gt; for results where we know there can be a failure. For example, &lt;code&gt;compose&lt;/code&gt; can fail if the result does not pass the connected and no crossing boundary check, and &lt;code&gt;force&lt;/code&gt; can fail if its argument is an incorrect &lt;code&gt;Tgraph&lt;/code&gt;. In situations when you would like to continue some computation rather than raise an error when there is a failure, use a &lt;em&gt;try&lt;/em&gt; version of a function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryCompose&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;tryForce&lt;/span&gt;   &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We define &lt;code&gt;Try&lt;/code&gt; as a synonym for &lt;code&gt;Either ShowS&lt;/code&gt; (which is a monad) in module &lt;code&gt;Tgraph.Try&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Try a = Either ShowS a&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Note &lt;code&gt;ShowS&lt;/code&gt; is &lt;code&gt;String -&amp;gt; String&lt;/code&gt;). Successful results have the form &lt;code&gt;Right r&lt;/code&gt; (for some correct result &lt;code&gt;r&lt;/code&gt;) and failure results have the form &lt;code&gt;Left (s&amp;lt;&amp;gt;)&lt;/code&gt; (where &lt;code&gt;s&lt;/code&gt; is a &lt;code&gt;String&lt;/code&gt; describing the problem as a failure report).&lt;/p&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;runTry&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;either&lt;/span&gt; &lt;span&gt;error&lt;/span&gt; &lt;span&gt;id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will retrieve a correct result but raise an error for failure cases. This means we can always derive an error raising version from a try version of a function by composing with &lt;code&gt;runTry&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;
    &lt;span&gt;compose&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;tryCompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Elementary Tgraph and TileFace Operations&lt;/h3&gt;
&lt;p&gt;The module &lt;code&gt;Tgraph.Prelude&lt;/code&gt; defines elementary operations on &lt;code&gt;Tgraph&lt;/code&gt;s relating vertices, directed edges, and faces. We describe a few of them here.&lt;/p&gt;
&lt;p&gt;When we need to refer to particular vertices of a &lt;code&gt;TileFace&lt;/code&gt; we use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;originV&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt; &lt;span&gt;-- the first vertex - red dot in figure 2&lt;/span&gt;
    &lt;span&gt;oppV&lt;/span&gt;    &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt; &lt;span&gt;-- the vertex at the opposite end of the join edge from the origin&lt;/span&gt;
    &lt;span&gt;wingV&lt;/span&gt;   &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt; &lt;span&gt;-- the vertex not on the join edge&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A directed edge is represented as a pair of vertices.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;(a,b)&lt;/code&gt; is regarded as a directed edge from a to b.&lt;/p&gt;
&lt;p&gt;When we need to refer to particular edges of a &lt;code&gt;TileFace&lt;/code&gt; we use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;joinE&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;  &lt;span&gt;-- shown dotted in figure 2&lt;/span&gt;
    &lt;span&gt;shortE&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;  &lt;span&gt;-- the non-join short edge&lt;/span&gt;
    &lt;span&gt;longE&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;  &lt;span&gt;-- the non-join long edge&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which are all directed clockwise round the &lt;code&gt;TileFace&lt;/code&gt;. In contrast, &lt;code&gt;joinOfTile&lt;/code&gt; is always directed away from the origin vertex, so is not clockwise for right darts or for left kites:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;joinOfTile&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt;
    &lt;span&gt;joinOfTile&lt;/span&gt; &lt;span&gt;face&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;originV&lt;/span&gt; &lt;span&gt;face&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;oppV&lt;/span&gt; &lt;span&gt;face&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the special case that a list of directed edges is symmetrically closed [(b,a) is in the list whenever (a,b) is in the list] we can think of this as an edge list rather than just a directed edge list.&lt;/p&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;internalEdges&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;produces an edge list, whereas&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;boundary&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;produces single directions. Each directed edge in the resulting boundary will have a &lt;code&gt;TileFace&lt;/code&gt; on the left and an exterior region on the right. The function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;dedges&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;produces all the directed edges obtained by going clockwise round each &lt;code&gt;TileFace&lt;/code&gt; so not every edge in the list has an inverse in the list.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There is now a class &lt;code&gt;HasFaces&lt;/code&gt; (introduced in version 1.4) which includes instances for both &lt;code&gt;Tgraph&lt;/code&gt; and &lt;code&gt;[TileFace]&lt;/code&gt; and others. This allows some generalisations. For example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;faces&lt;/span&gt;         &lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
    &lt;span&gt;internalEdges&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;
    &lt;span&gt;boundary&lt;/span&gt;      &lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; 
    &lt;span&gt;dedges&lt;/span&gt;        &lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; 
    &lt;span&gt;nullFaces&lt;/span&gt;     &lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Patches (Scaled and Positioned Tilings)&lt;/h3&gt;
&lt;p&gt;Behind the scenes, when a &lt;code&gt;Tgraph&lt;/code&gt; is drawn, each &lt;code&gt;TileFace&lt;/code&gt; is converted to a &lt;code&gt;Piece&lt;/code&gt;. A &lt;code&gt;Piece&lt;/code&gt; is another specialisation of &lt;code&gt;HalfTile&lt;/code&gt; using a two dimensional vector to indicate the length and direction of the join edge of the half-tile (from the &lt;code&gt;originV&lt;/code&gt; to the &lt;code&gt;oppV&lt;/code&gt;), thus fixing its scale and orientation. The whole &lt;code&gt;Tgraph&lt;/code&gt; then becomes a list of located &lt;code&gt;Piece&lt;/code&gt;s called a &lt;code&gt;Patch&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;HalfTile&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;V2&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;Patch&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Located&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;Piece&lt;/code&gt; drawing functions derive vectors for other edges of a half-tile piece from its join edge vector. In particular (in the &lt;code&gt;TileLib&lt;/code&gt; module) we have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;drawPiece&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;darawjPiece&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;fillPieceDK&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the first draws the non-join edges of a &lt;code&gt;Piece&lt;/code&gt;, the second does the same but adds a faint dashed line for the join edge, and the third takes two colours – one for darts and one for kites, which are used to fill the piece as well as using &lt;code&gt;drawPiece&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Patch&lt;/code&gt; is an instance of class &lt;code&gt;Transformable&lt;/code&gt; so a &lt;code&gt;Patch&lt;/code&gt; can be scaled, rotated, and translated.&lt;/p&gt;
&lt;h3&gt;Vertex Patches&lt;/h3&gt;
&lt;p&gt;It is useful to have an intermediate form between &lt;code&gt;Tgraph&lt;/code&gt;s and &lt;code&gt;Patch&lt;/code&gt;es, that contains information about both the location of vertices (as 2D points), and the abstract &lt;code&gt;TileFace&lt;/code&gt;s. This allows us to introduce labelled drawing functions (to show the vertex labels) which we then extend to &lt;code&gt;Tgraph&lt;/code&gt;s. We call the intermediate form a &lt;code&gt;VPatch&lt;/code&gt; (short for Vertex Patch).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;VertexLocMap&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;IntMap.IntMap&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Point&lt;/span&gt; &lt;span&gt;V2&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
    &lt;span&gt;data&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;span&gt;vLocs&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;VertexLocMap&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;  &lt;span&gt;vpFaces&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;}&lt;/span&gt; &lt;span&gt;deriving&lt;/span&gt; &lt;span&gt;Show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;makeVP&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;calculates vertex locations using a default orientation and scale.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;VPatch&lt;/code&gt; is made an instance of class &lt;code&gt;Transformable&lt;/code&gt; so a &lt;code&gt;VPatch&lt;/code&gt; can also be scaled and rotated.&lt;/p&gt;
&lt;p&gt;One essential use of this intermediate form is to be able to draw a &lt;code&gt;Tgraph&lt;/code&gt; with labels, rotated but without the labels themselves being rotated. We can simply convert the &lt;code&gt;Tgraph&lt;/code&gt; to a &lt;code&gt;VPatch&lt;/code&gt;, and rotate that before drawing with labels.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;someAngle&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;makeVP&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also align a &lt;code&gt;VPatch&lt;/code&gt; using vertex labels.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;alignXaxis&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So if &lt;code&gt;g&lt;/code&gt; is a &lt;code&gt;Tgraph&lt;/code&gt; with vertex labels &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; we can align it on the x-axis with &lt;code&gt;a&lt;/code&gt; at the origin and &lt;code&gt;b&lt;/code&gt; on the positive x-axis (after converting to a &lt;code&gt;VPatch&lt;/code&gt;), instead of accepting the default orientation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;alignXaxis&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;makeVP&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another use of &lt;code&gt;VPatch&lt;/code&gt;es is to share the vertex location map when drawing only subsets of the faces (see &lt;em&gt;Overlaid examples&lt;/em&gt; in the next section).&lt;/p&gt;
&lt;h2&gt;4. Drawing in More Detail&lt;/h2&gt;
&lt;h3&gt;Class Drawable&lt;/h3&gt;
&lt;p&gt;There is a class &lt;code&gt;Drawable&lt;/code&gt; with instances &lt;code&gt;Tgraph&lt;/code&gt;, &lt;code&gt;VPatch&lt;/code&gt;, &lt;code&gt;Patch&lt;/code&gt;. When the token &lt;code&gt;B&lt;/code&gt; is in scope standing for a fixed backend then we can assume&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;draw&lt;/span&gt;   &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;  &lt;span&gt;-- draws non-join edges&lt;/span&gt;
    &lt;span&gt;drawj&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;  &lt;span&gt;-- as with draw but also draws dashed join edges&lt;/span&gt;
    &lt;span&gt;fillDK&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt; &lt;span&gt;-- fills with colours&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;fillDK clr1 clr2&lt;/code&gt; will fill darts with colour &lt;code&gt;clr1&lt;/code&gt; and kites with colour &lt;code&gt;clr2&lt;/code&gt; as well as drawing non-join edges.&lt;/p&gt;
&lt;p&gt;These are the main drawing tools. However they are actually defined for any suitable backend &lt;code&gt;b&lt;/code&gt; so have more general types.&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Update Sept 2024&lt;/em&gt;) From version 1.1 onwards of PenroseKiteDart, these are&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;::&lt;/span&gt;   &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;OKBackend&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt;
              &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;
    &lt;span&gt;drawj&lt;/span&gt; &lt;span&gt;::&lt;/span&gt;  &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;OKBackend&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt;
              &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;
    &lt;span&gt;fillDK&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;OKBackend&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt;
              &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where the class &lt;code&gt;OKBackend&lt;/code&gt; is a check to ensure a backend is suitable for drawing 2D tilings with or without labels.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In these notes we will generally use the simpler description of types using &lt;code&gt;B&lt;/code&gt; for a fixed chosen backend for the sake of clarity.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The drawing tools are each defined via the class function &lt;code&gt;drawWith&lt;/code&gt; using &lt;code&gt;Piece&lt;/code&gt; drawing functions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;class&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;where&lt;/span&gt;
        &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Piece&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    
    &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;drawPiece&lt;/span&gt;
    &lt;span&gt;drawj&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;drawjPiece&lt;/span&gt;
    &lt;span&gt;fillDK&lt;/span&gt; &lt;span&gt;clr1&lt;/span&gt; &lt;span&gt;clr2&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;fillPieceDK&lt;/span&gt; &lt;span&gt;clr1&lt;/span&gt; &lt;span&gt;clr2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To design a new drawing function, you only need to implement a function to draw a &lt;code&gt;Piece&lt;/code&gt;, (let us call it &lt;code&gt;newPieceDraw&lt;/code&gt;)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;newPieceDraw&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Piece&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can then be elevated to draw any &lt;code&gt;Drawable&lt;/code&gt; (including &lt;code&gt;Tgraph&lt;/code&gt;s, &lt;code&gt;VPatch&lt;/code&gt;es, and &lt;code&gt;Patch&lt;/code&gt;es) by applying the &lt;code&gt;Drawable&lt;/code&gt; class function &lt;code&gt;drawWith&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;newDraw&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Drawable&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;newDraw&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;drawWith&lt;/span&gt; &lt;span&gt;newPieceDraw&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Class DrawableLabelled&lt;/h3&gt;
&lt;p&gt;Class &lt;code&gt;DrawableLabelled&lt;/code&gt; is defined with instances &lt;code&gt;Tgraph&lt;/code&gt; and &lt;code&gt;VPatch&lt;/code&gt;, but &lt;code&gt;Patch&lt;/code&gt; is not an instance (because this does not retain vertex label information).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;class&lt;/span&gt; &lt;span&gt;DrawableLabelled&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;where&lt;/span&gt;
        &lt;span&gt;labelColourSize&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Colour&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Measure&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Patch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;labelColourSize c m&lt;/code&gt; modifies a &lt;code&gt;Patch&lt;/code&gt; drawing function to add labels (of colour &lt;code&gt;c&lt;/code&gt; and size measure &lt;code&gt;m&lt;/code&gt;). &lt;code&gt;Measure&lt;/code&gt; is defined in Diagrams.Prelude with pre-defined measures &lt;code&gt;tiny&lt;/code&gt;, &lt;code&gt;verySmall&lt;/code&gt;, &lt;code&gt;small&lt;/code&gt;, &lt;code&gt;normal&lt;/code&gt;, &lt;code&gt;large&lt;/code&gt;, &lt;code&gt;veryLarge&lt;/code&gt;, &lt;code&gt;huge&lt;/code&gt;. For most of our diagrams of &lt;code&gt;Tgraph&lt;/code&gt;s, we use red labels and we also find &lt;code&gt;small&lt;/code&gt; is a good default size choice, so we define&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;labelSize&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;DrawableLabelled&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Measure&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Patch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;labelSize&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;labelColourSize&lt;/span&gt; &lt;span&gt;red&lt;/span&gt;

    &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;DrawableLabelled&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Patch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;labelSize&lt;/span&gt; &lt;span&gt;small&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and then &lt;code&gt;labelled draw&lt;/code&gt;, &lt;code&gt;labelled drawj&lt;/code&gt;, &lt;code&gt;labelled (fillDK clr1 clr2)&lt;/code&gt; can all be used on both &lt;code&gt;Tgraph&lt;/code&gt;s and &lt;code&gt;VPatch&lt;/code&gt;es as well as (for example) &lt;code&gt;labelSize tiny draw&lt;/code&gt;, or &lt;code&gt;labelCoulourSize blue normal drawj&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Further drawing functions&lt;/h3&gt;
&lt;p&gt;There are a few extra drawing functions built on top of the above ones. The function &lt;code&gt;smart&lt;/code&gt; is a modifier to add dashed join edges only when they occur on the boundary of a &lt;code&gt;Tgraph&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So &lt;code&gt;smart vpdraw g&lt;/code&gt; will draw dashed join edges on the boundary of &lt;code&gt;g&lt;/code&gt; before applying the drawing function &lt;code&gt;vpdraw&lt;/code&gt; to the &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;g&lt;/code&gt;. For example the following all draw dashed join edges only on the boundary for a &lt;code&gt;Tgraph g&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelSize&lt;/span&gt; &lt;span&gt;normal&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When using labels, the function &lt;code&gt;rotating&lt;/code&gt; allows a &lt;code&gt;Tgraph&lt;/code&gt; to be drawn rotated without rotating the labels.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;rotating&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Angle&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;rotating&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;makeVP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So for example,&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;rotating&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;90&lt;/span&gt;&lt;span&gt;@@&lt;/span&gt;&lt;span&gt;deg&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;makes sense for a &lt;code&gt;Tgraph g&lt;/code&gt;. Of course if there are no labels we can simply use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;90&lt;/span&gt;&lt;span&gt;@@&lt;/span&gt;&lt;span&gt;deg&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;draw&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly &lt;code&gt;aligning&lt;/code&gt; allows a &lt;code&gt;Tgraph&lt;/code&gt; to be aligned on the X-axis using a pair of vertex numbers before drawing.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;aligning&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;aligning&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;vpdraw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;alignXaxis&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;makeVP&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, for example, if &lt;code&gt;Tgraph g&lt;/code&gt; has vertices &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, both&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;aligning&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;aligning&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;make sense. Note that the following two examples are &lt;strong&gt;wrong&lt;/strong&gt;. Even though they type check, they re-orient &lt;code&gt;g&lt;/code&gt; without repositioning the boundary joins.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;rotate&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;      &lt;span&gt;-- WRONG&lt;/span&gt;
    &lt;span&gt;smart&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;alignXaxis&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;  &lt;span&gt;-- WRONG&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;smartRotating&lt;/span&gt; &lt;span&gt;angle&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;
    &lt;span&gt;smartAligning&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;a&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;b&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;labelled&lt;/span&gt; &lt;span&gt;draw&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;smartRotatinge&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Angle&lt;/span&gt; &lt;span&gt;Double&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;
    &lt;span&gt;smartAligning&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;are defined using&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;smartOn&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, &lt;code&gt;smartOn g vpdraw vp&lt;/code&gt; uses the given &lt;code&gt;vp&lt;/code&gt; for drawing boundary joins and drawing faces of &lt;code&gt;g&lt;/code&gt; (with &lt;code&gt;vpdraw&lt;/code&gt;) rather than converting &lt;code&gt;g&lt;/code&gt; to a new &lt;code&gt;VPatch&lt;/code&gt;. This assumes &lt;code&gt;vp&lt;/code&gt; has locations for vertices in &lt;code&gt;g&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Overlaid examples (location map sharing)&lt;/h3&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;drawForce&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will (smart) draw a &lt;code&gt;Tgraph g&lt;/code&gt; in red overlaid (using &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;) on the result of &lt;code&gt;force g&lt;/code&gt; as in figure 6. Similarly&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;drawPCompose&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;applied to a &lt;code&gt;Tgraph g&lt;/code&gt; will draw the result of a partial composition of &lt;code&gt;g&lt;/code&gt; as in figure 7. That is a drawing of &lt;code&gt;compose g&lt;/code&gt; but overlaid with a drawing of the remainder faces of &lt;code&gt;g&lt;/code&gt; shown in pale green.&lt;/p&gt;
&lt;p&gt;Both these functions make use of sharing a vertex location map to get correct alignments of overlaid diagrams. In the case of &lt;code&gt;drawForce g&lt;/code&gt;, we know that a &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;force g&lt;/code&gt; will contain all the vertex locations for &lt;code&gt;g&lt;/code&gt; since force only adds to a &lt;code&gt;Tgraph&lt;/code&gt; (when it succeeds). So when constructing the diagram for &lt;code&gt;g&lt;/code&gt; we can use the &lt;code&gt;VPatch&lt;/code&gt; created for &lt;code&gt;force g&lt;/code&gt; instead of starting afresh. Similarly for &lt;code&gt;drawPCompose g&lt;/code&gt; the &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;g&lt;/code&gt; contains locations for all the vertices of &lt;code&gt;compose g&lt;/code&gt; so &lt;code&gt;compose g&lt;/code&gt; is drawn using the &lt;code&gt;VPatch&lt;/code&gt; for &lt;code&gt;g&lt;/code&gt; instead of starting afresh.&lt;/p&gt;
&lt;p&gt;The location map sharing is done with&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;subFaces&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; 
                &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;so that &lt;code&gt;subFaces fcs vp&lt;/code&gt; is a &lt;code&gt;VPatch&lt;/code&gt; with the same vertex locations as &lt;code&gt;vp&lt;/code&gt;, but replacing the faces of &lt;code&gt;vp&lt;/code&gt; with &lt;code&gt;fcs&lt;/code&gt;. [Of course, this can go wrong if the new faces have vertices not in the domain of the vertex location map so this needs to be used with care. Any errors would only be discovered when a diagram is created.]&lt;/p&gt;
&lt;p&gt;For cases where labels are only going to be drawn for certain faces, we need a version of &lt;code&gt;subFaces&lt;/code&gt; which also gets rid of vertex locations that are not relevant to the faces. For this situation we have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;restrictTo&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;HasFaces&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; 
                 &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;VPatch&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which filters out un-needed vertex locations from the vertex location map. Unlike &lt;code&gt;subFaces&lt;/code&gt;, &lt;code&gt;restrictTo&lt;/code&gt; checks for missing vertex locations, so &lt;code&gt;restrictTo fcs vp&lt;/code&gt; raises an error if a vertex in &lt;code&gt;fcs&lt;/code&gt; is missing from the keys of the vertex location map of &lt;code&gt;vp&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;5. Forcing in More Detail&lt;/h2&gt;
&lt;h3&gt;The force rules&lt;/h3&gt;
&lt;p&gt;The rules used by our force algorithm are local and derived from the fact that there are seven possible vertex types as depicted in figure 8.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/verttypesfig.png?w=625"&gt;&lt;figcaption&gt;Figure 8: Seven vertex types&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Our rules are shown in figure 9 (omitting mirror symmetric versions). In each case the &lt;code&gt;TileFace&lt;/code&gt; shown yellow needs to be added in the presence of the other &lt;code&gt;TileFace&lt;/code&gt;s shown.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/forcerules.png?w=625"&gt;&lt;figcaption&gt;Figure 9: Rules for forcing&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;Main Forcing Operations&lt;/h3&gt;
&lt;p&gt;To make forcing efficient we convert a &lt;code&gt;Tgraph&lt;/code&gt; to a &lt;code&gt;BoundaryState&lt;/code&gt; to keep track of boundary information of the &lt;code&gt;Tgraph&lt;/code&gt;, and then calculate a &lt;code&gt;ForceState&lt;/code&gt; which combines the &lt;code&gt;BoundaryState&lt;/code&gt; with a record of awaiting boundary edge updates (an update map). Then each face addition is carried out on a &lt;code&gt;ForceState&lt;/code&gt;, converting back when all the face additions are complete. It makes sense to apply &lt;code&gt;force&lt;/code&gt; (and related functions) to a &lt;code&gt;Tgraph&lt;/code&gt;, a &lt;code&gt;BoundaryState&lt;/code&gt;, or a &lt;code&gt;ForceState&lt;/code&gt;, so we define a class &lt;code&gt;Forcible&lt;/code&gt; with instances &lt;code&gt;Tgraph&lt;/code&gt;, &lt;code&gt;BoundaryState&lt;/code&gt;, and &lt;code&gt;ForceState&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This allows us to define&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first will raise an error if a stuck tiling is encountered. The second uses a &lt;code&gt;Try&lt;/code&gt; result which produces a &lt;code&gt;Left string&lt;/code&gt; for failures and a &lt;code&gt;Right a&lt;/code&gt; for successful result &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are several other operations related to forcing including&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;stepForce&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryStepForce&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Int&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;

    &lt;span&gt;addHalfDart&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;addHalfKite&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryAddHalfDart&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;tryAddHalfKite&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first two force (up to) a given number of steps (=face additions) and the other four add a half dart/kite on a given boundary edge.&lt;/p&gt;
&lt;h3&gt;Update Generators&lt;/h3&gt;
&lt;p&gt;An update generator is used to calculate which boundary edges can have a certain update. There is an update generator for each force rule, but also a combined (all update) generator. The force operations mentioned above all use the default all update generator (&lt;code&gt;defaultAllUGen&lt;/code&gt;) but there are more general (&lt;em&gt;with&lt;/em&gt;) versions that can be passed an update generator of choice. For example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;forceWith&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryForceWith&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In fact we defined&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;forceWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;
    &lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;tryForceWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also define&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;wholeTiles&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;wholeTiles&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;forceWith&lt;/span&gt; &lt;span&gt;wholeTileUpdates&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;wholeTileUpdates&lt;/code&gt; is an update generator that just finds boundary join edges to complete whole tiles.&lt;/p&gt;
&lt;p&gt;In addition to &lt;code&gt;defaultAllUGen&lt;/code&gt; there is also &lt;code&gt;allUGenerator&lt;/code&gt; which does the same thing apart from how failures are reported. The reason for keeping both is that they were constructed differently and so are useful for testing.&lt;/p&gt;
&lt;p&gt;In fact &lt;code&gt;UpdateGenerator&lt;/code&gt;s are functions that take a &lt;code&gt;BoundaryState&lt;/code&gt; and a focus (list of boundary directed edges) to produce an update map. Each &lt;code&gt;Update&lt;/code&gt; is calculated as either a &lt;code&gt;SafeUpdate&lt;/code&gt; (where two of the new face edges are on the existing boundary and no new vertex is needed) or an &lt;code&gt;UnsafeUpdate&lt;/code&gt; (where only one edge of the new face is on the boundary and a new vertex needs to be created for a new face).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;BoundaryState&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;UpdateMap&lt;/span&gt;
    &lt;span&gt;type&lt;/span&gt; &lt;span&gt;UpdateMap&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;Map.Map&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;Update&lt;/span&gt;
    &lt;span&gt;data&lt;/span&gt; &lt;span&gt;Update&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;SafeUpdate&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt; 
                &lt;span&gt;|&lt;/span&gt; &lt;span&gt;UnsafeUpdate&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Vertex&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Completing (executing) an &lt;code&gt;UnsafeUpdate&lt;/code&gt; requires a touching vertex check to ensure that the new vertex does not clash with an existing boundary vertex. Using an existing (touching) vertex would create a crossing boundary so such an update has to be blocked.&lt;/p&gt;
&lt;h3&gt;Forcible Class Operations&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Forcible&lt;/code&gt; class operations are higher order and designed to allow for easy additions of further generic operations. They take care of conversions between &lt;code&gt;Tgraph&lt;/code&gt;s, &lt;code&gt;BoundaryState&lt;/code&gt;s and &lt;code&gt;ForceState&lt;/code&gt;s.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;class&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;where&lt;/span&gt;
      &lt;span&gt;tryFSOpWith&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;ForceState&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
      &lt;span&gt;tryChangeBoundaryWith&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;BoundaryState&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;BoundaryChange&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
      &lt;span&gt;tryInitFSWith&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;UpdateGenerator&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For example, given an update generator &lt;code&gt;ugen&lt;/code&gt; and any &lt;code&gt;f:: ForceState -&amp;gt; Try ForceState&lt;/code&gt; , then &lt;code&gt;f&lt;/code&gt; can be generalised to work on any &lt;code&gt;Forcible&lt;/code&gt; using &lt;code&gt;tryFSOpWith ugen f&lt;/code&gt;. This is used to define both &lt;code&gt;tryForceWith&lt;/code&gt; and &lt;code&gt;tryStepForceWith&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We also specialize &lt;code&gt;tryFSOpWith&lt;/code&gt; to use the default update generator&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryFSOp&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;ForceState&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryFSOp&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;tryFSOpWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly given an update generator &lt;code&gt;ugen&lt;/code&gt; and any &lt;code&gt;f:: BoundaryState -&amp;gt; Try BoundaryChange&lt;/code&gt; , then &lt;code&gt;f&lt;/code&gt; can be generalised to work on any &lt;code&gt;Forcible&lt;/code&gt; using &lt;code&gt;tryChangeBoundaryWith ugen f&lt;/code&gt;. This is used to define &lt;code&gt;tryAddHalfDart&lt;/code&gt; and &lt;code&gt;tryAddHalfKite&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We also specialize &lt;code&gt;tryChangeBoundaryWith&lt;/code&gt; to use the default update generator&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryChangeBoundary&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;BoundaryState&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;BoundaryChange&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryChangeBoundary&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;tryChangeBoundaryWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the type &lt;code&gt;BoundaryChange&lt;/code&gt; contains a resulting &lt;code&gt;BoundaryState&lt;/code&gt;, the single &lt;code&gt;TileFace&lt;/code&gt; that has been added, a list of edges removed from the boundary (of the &lt;code&gt;BoundaryState&lt;/code&gt; prior to the face addition), and a list of the (3 or 4) boundary edges affected around the change that require checking or re-checking for updates.&lt;/p&gt;
&lt;p&gt;The class function &lt;code&gt;tryInitFSWith&lt;/code&gt; will use an update generator to create an initial &lt;code&gt;ForceState&lt;/code&gt; for any &lt;code&gt;Forcible&lt;/code&gt;. If the &lt;code&gt;Forcible&lt;/code&gt; is already a &lt;code&gt;ForceState&lt;/code&gt; it will do nothing. Otherwise it will calculate updates for the whole boundary. We also have the special case&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryInitFS&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;ForceState&lt;/span&gt;
    &lt;span&gt;tryInitFS&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;tryInitFSWith&lt;/span&gt; &lt;span&gt;defaultAllUGen&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Efficient chains of forcing operations.&lt;/h3&gt;
&lt;p&gt;Note that &lt;code&gt;(force . force)&lt;/code&gt; does the same as &lt;code&gt;force&lt;/code&gt;, but we might want to chain other &lt;code&gt;force&lt;/code&gt; related steps in a calculation.&lt;/p&gt;
&lt;p&gt;For example, consider the following combination which, after decomposing a &lt;code&gt;Tgraph&lt;/code&gt;, forces, then adds a half dart on a given boundary edge (&lt;code&gt;d&lt;/code&gt;) and then forces again.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;force&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;addHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;force&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since &lt;code&gt;decompose:: Tgraph -&amp;gt; Tgraph&lt;/code&gt;, the instances of &lt;code&gt;force&lt;/code&gt; and &lt;code&gt;addHalfDart d&lt;/code&gt; will have type &lt;code&gt;Tgraph -&amp;gt; Tgraph&lt;/code&gt; so each of these operations, will begin and end with conversions between &lt;code&gt;Tgraph&lt;/code&gt; and &lt;code&gt;ForceState&lt;/code&gt;. We would do better to avoid these wasted intermediate conversions working only with &lt;code&gt;ForceState&lt;/code&gt;s and keeping only those necessary conversions at the beginning and end of the whole sequence.&lt;/p&gt;
&lt;p&gt;This can be done using &lt;code&gt;tryFSOp&lt;/code&gt;. To see this, let us first re-express the forcing sequence using the &lt;code&gt;Try&lt;/code&gt; monad, so&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;addHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;force&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;becomes&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryAddHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that (&lt;code&gt;&amp;lt;=&amp;lt;&lt;/code&gt;) is the Kliesli arrow which replaces composition for Monads (defined in Control.Monad). (We could also have expressed this right to left sequence with a left to right version &lt;code&gt;tryForce &amp;gt;=&amp;gt; tryAddHalfDart d &amp;gt;=&amp;gt; tryForce&lt;/code&gt;). The definition of &lt;code&gt;combo&lt;/code&gt; becomes&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryAddHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This has no performance improvement, but now we can pass the sequence to &lt;code&gt;tryFSOp&lt;/code&gt; to remove the unnecessary conversions between steps.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Dedge&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
    &lt;span&gt;combo&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;runTry&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;tryFSOp&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;tryForce&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryAddHalfDart&lt;/span&gt; &lt;span&gt;d&lt;/span&gt; &lt;span&gt;&amp;lt;=&amp;lt;&lt;/span&gt; &lt;span&gt;tryForce&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;decompose&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The sequence actually has type &lt;code&gt;Forcible a =&amp;gt; a -&amp;gt; Try a&lt;/code&gt; but when passed to &lt;code&gt;tryFSOp&lt;/code&gt; it specialises to type &lt;code&gt;ForceState -&amp;gt; Try ForseState&lt;/code&gt;. This ensures the sequence works on a &lt;code&gt;ForceState&lt;/code&gt; and any conversions are confined to the beginning and end of the sequence, avoiding unnecessary intermediate conversions.&lt;/p&gt;
&lt;h3&gt;A limitation of forcing&lt;/h3&gt;
&lt;p&gt;To avoid creating touching vertices (or crossing boundaries) a &lt;code&gt;BoundaryState&lt;/code&gt; keeps track of locations of boundary vertices. At around 35,000 face additions in a single &lt;code&gt;force&lt;/code&gt; operation the calculated positions of boundary vertices can become too inaccurate to prevent touching vertex problems. In such cases it is better to use&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;recalibratingForce&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;
    &lt;span&gt;tryRecalibratingForce&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These work by recalculating all vertex positions at 20,000 step intervals to get more accurate boundary vertex positions. For example, 6 decompositions of the &lt;code&gt;kingGraph&lt;/code&gt; has 2,906 faces. Applying &lt;code&gt;force&lt;/code&gt; to this should result in 53,574 faces but will go wrong before it reaches that. This can be fixed by calculating either&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;recalibratingForce&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;decompositions&lt;/span&gt; &lt;span&gt;kingGraph&lt;/span&gt; &lt;span&gt;!!&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or using an extra &lt;code&gt;force&lt;/code&gt; before the decompositions&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;force&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;decompositions&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;force&lt;/span&gt; &lt;span&gt;kingGraph&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;!!&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the latter case, the final &lt;code&gt;force&lt;/code&gt; only needs to add 17,864 faces to the 35,710 produced by &lt;code&gt;decompositions (force kingGraph) !!6&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;6. Advanced Operations&lt;/h2&gt;
&lt;h3&gt;Guided comparison of &lt;code&gt;Tgraph&lt;/code&gt;s&lt;/h3&gt;
&lt;p&gt;Asking if two &lt;code&gt;Tgraph&lt;/code&gt;s are equivalent (the same apart from choice of vertex numbers) is a an np-complete problem. However, we do have an efficient &lt;em&gt;guided&lt;/em&gt; way of comparing &lt;code&gt;Tgraph&lt;/code&gt;s. In the module &lt;code&gt;Tgraph.Rellabelling&lt;/code&gt; we have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;sameGraph&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Bool&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The expression &lt;code&gt;sameGraph (g1,d1) (g2,d2)&lt;/code&gt; asks if &lt;code&gt;g2&lt;/code&gt; can be relabelled to match &lt;code&gt;g1&lt;/code&gt; assuming that the directed edge &lt;code&gt;d2&lt;/code&gt; in &lt;code&gt;g2&lt;/code&gt; is identified with &lt;code&gt;d1&lt;/code&gt; in &lt;code&gt;g1&lt;/code&gt;. Hence the comparison is guided by the assumption that &lt;code&gt;d2&lt;/code&gt; corresponds to &lt;code&gt;d1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It is implemented using&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryRelabelToMatch&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;tryRelabelToMatch (g1,d1) (g2,d2)&lt;/code&gt; will either fail with a &lt;code&gt;Left report&lt;/code&gt; if a mismatch is found when relabelling &lt;code&gt;g2&lt;/code&gt; to match &lt;code&gt;g1&lt;/code&gt; or will succeed with &lt;code&gt;Right g3&lt;/code&gt; where &lt;code&gt;g3&lt;/code&gt; is a relabelled version of &lt;code&gt;g2&lt;/code&gt;. The successful result &lt;code&gt;g3&lt;/code&gt; will match &lt;code&gt;g1&lt;/code&gt; in a maximal tile-connected collection of faces containing the face with edge &lt;code&gt;d1&lt;/code&gt; and have vertices disjoint from those of &lt;code&gt;g1&lt;/code&gt; elsewhere. The comparison tries to grow a suitable relabelling by comparing faces one at a time starting from the face with edge &lt;code&gt;d1&lt;/code&gt; in &lt;code&gt;g1&lt;/code&gt; and the face with edge &lt;code&gt;d2&lt;/code&gt; in &lt;code&gt;g2&lt;/code&gt;. (This relies on the fact that &lt;code&gt;Tgraph&lt;/code&gt;s are connected with no crossing boundaries, and hence tile-connected.)&lt;/p&gt;
&lt;p&gt;The above function is also used to implement&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;tryFullUnion&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which tries to find the union of two &lt;code&gt;Tgraph&lt;/code&gt;s guided by a directed edge identification. However, there is an extra complexity arising from the fact that &lt;code&gt;Tgraph&lt;/code&gt;s might &lt;em&gt;overlap&lt;/em&gt; in more than one tile-connected region. After calculating one overlapping region, the full union uses some geometry (calculating vertex locations) to detect further overlaps.&lt;/p&gt;
&lt;p&gt;Finally we have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;commonFaces&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;Dedge&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which will find common regions of overlapping faces of two &lt;code&gt;Tgraph&lt;/code&gt;s guided by a directed edge identification. The resulting common faces will be a sub-collection of faces from the first &lt;code&gt;Tgraph&lt;/code&gt;. These are returned as a list as they may not be a connected collection of faces and therefore not necessarily a &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Empires and SuperForce&lt;/h3&gt;
&lt;p&gt;In &lt;a href="https://readerunner.wordpress.com/2023/04/26/graphs-kites-and-darts-empires-and-superforce/"&gt;Empires and SuperForce&lt;/a&gt; we discussed forced boundary coverings which were used to implement both a &lt;code&gt;superForce&lt;/code&gt; operation&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;superForce&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and operations to calculate empires.&lt;/p&gt;
&lt;p&gt;We will not repeat the descriptions here other than to note that&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;forcedBoundaryECovering&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;finds boundary edge coverings after forcing a &lt;code&gt;Tgraph&lt;/code&gt;. That is, &lt;code&gt;forcedBoundaryECovering g&lt;/code&gt; will first force &lt;code&gt;g&lt;/code&gt;, then (if it succeeds) finds a collection of (forced) extensions to &lt;code&gt;force g&lt;/code&gt; such that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;each extension has the whole boundary of &lt;code&gt;force g&lt;/code&gt; as internal edges.&lt;/li&gt;
&lt;li&gt;each possible addition to a boundary edge of &lt;code&gt;force g&lt;/code&gt; (kite or dart) has been included in the collection.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(&lt;em&gt;possible&lt;/em&gt; here means – not leading to a stuck &lt;code&gt;Tgraph&lt;/code&gt; when forced.) There is also&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;forcedBoundaryVCovering&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which does the same except that the extensions have all boundary vertices internal rather than just the boundary edges. In both cases the result is a list of explicitly forced Tgraphs (discussed next).&lt;/p&gt;
&lt;h3&gt;Combinations and Explicitly Forced&lt;/h3&gt;
&lt;p&gt;We introduced a new type &lt;code&gt;Forced&lt;/code&gt; (in v 1.3) to enable a forcible to be explictily labelled as being forced. For example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;forceF&lt;/span&gt;    &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; 
    &lt;span&gt;tryForceF&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forcible&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;=&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Try&lt;/span&gt; &lt;span&gt;(&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;
    &lt;span&gt;forgetF&lt;/span&gt;   &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;a&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This allows us to restrict certain functions which expect a forced argument by making this explicit.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;composeF&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The definition makes use of theorems established in &lt;a href="https://readerunner.wordpress.com/2023/09/12/graphs-kites-and-darts-and-theorems/"&gt;Graphs,Kites and Darts and Theorems&lt;/a&gt; that composing a forced &lt;code&gt;Tgraph&lt;/code&gt; does not require a check (for connectedness and no crossing boundaries) and the result is also forced. This can then be used to define efficient combinations such as&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;compForce&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;      &lt;span&gt;-- compose after forcing&lt;/span&gt;
    &lt;span&gt;compForce&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;composeF&lt;/span&gt; &lt;span&gt;.&lt;/span&gt; &lt;span&gt;forceF&lt;/span&gt;

    &lt;span&gt;allCompForce&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-- iterated (compose after force) while not emptyTgraph&lt;/span&gt;
    &lt;span&gt;maxCompForce&lt;/span&gt;&lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Forced&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;   &lt;span&gt;-- last item in allCompForce (or emptyTgraph)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Tracked Tgraphs&lt;/h3&gt;
&lt;p&gt;The type&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;data&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span&gt;=&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt;
       &lt;span&gt;{&lt;/span&gt; &lt;span&gt;tgraph&lt;/span&gt;  &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt;
       &lt;span&gt;,&lt;/span&gt; &lt;span&gt;tracked&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;TileFace&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; 
       &lt;span&gt;}&lt;/span&gt; &lt;span&gt;deriving&lt;/span&gt; &lt;span&gt;Show&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;has proven useful in experimentation as well as in producing artwork with darts and kites. The idea is to keep a record of sub-collections of faces of a &lt;code&gt;Tgraph&lt;/code&gt; when doing both force operations and decompositions. A list of the sub-collections forms the tracked list associated with the &lt;code&gt;Tgraph&lt;/code&gt;. We make &lt;code&gt;TrackedTgraph&lt;/code&gt; an instance of class &lt;code&gt;Forcible&lt;/code&gt; by having force operations only affect the &lt;code&gt;Tgraph&lt;/code&gt; and not the tracked list. The significant idea is the implementation of&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;decomposeTracked&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Decomposition of a &lt;code&gt;Tgraph&lt;/code&gt; involves introducing a new vertex for each long edge and each kite join. These are then used to construct the decomposed faces. For &lt;code&gt;decomposeTracked&lt;/code&gt; we do the same for the &lt;code&gt;Tgraph&lt;/code&gt;, but when it comes to the tracked collections, we decompose them re-using the same new vertex numbers calculated for the edges in the &lt;code&gt;Tgraph&lt;/code&gt;. This keeps a consistent numbering between the &lt;code&gt;Tgraph&lt;/code&gt; and tracked faces, so each item in the tracked list remains a sub-collection of faces in the &lt;code&gt;Tgraph&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;drawTrackedTgraph&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;[&lt;/span&gt;&lt;span&gt;VPatch&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;span&gt;]&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is used to draw a &lt;code&gt;TrackedTgraph&lt;/code&gt;. It uses a list of functions to draw &lt;code&gt;VPatch&lt;/code&gt;es. The first drawing function is applied to a &lt;code&gt;VPatch&lt;/code&gt; for any untracked faces. Subsequent functions are applied to &lt;code&gt;VPatch&lt;/code&gt;es for the tracked list in order. Each diagram is beneath later ones in the list, with the diagram for the untracked faces at the bottom. The &lt;code&gt;VPatch&lt;/code&gt;es used are all restrictions of a single &lt;code&gt;VPatch&lt;/code&gt; for the &lt;code&gt;Tgraph&lt;/code&gt;, so will be consistent in vertex locations. When labels are used, there is also a &lt;code&gt;drawTrackedTgraphRotating&lt;/code&gt; and &lt;code&gt;drawTrackedTgraphAligning&lt;/code&gt; for rotating or aligning the &lt;code&gt;VPatch&lt;/code&gt; prior to applying the drawing functions.&lt;/p&gt;
&lt;p&gt;Note that the result of calculating empires (see &lt;a href="https://readerunner.wordpress.com/2023/04/26/graphs-kites-and-darts-empires-and-superforce/"&gt;Empires and SuperForce&lt;/a&gt; ) is represented as a &lt;code&gt;TrackedTgraph&lt;/code&gt;. The result is actually the common faces of a forced boundary covering, but a particular element of the covering (the first one) is chosen as the background &lt;code&gt;Tgraph&lt;/code&gt; with the common faces as a tracked sub-collection of faces. Hence we have&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &lt;span&gt;empire1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;empire2&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;Tgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt;
    
    &lt;span&gt;drawEmpire&lt;/span&gt; &lt;span&gt;::&lt;/span&gt; &lt;span&gt;TrackedTgraph&lt;/span&gt; &lt;span&gt;-&amp;gt;&lt;/span&gt; &lt;span&gt;Diagram&lt;/span&gt; &lt;span&gt;B&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Figure 10 was also created using &lt;code&gt;TrackedTgraph&lt;/code&gt;s.&lt;/p&gt;
&lt;figure&gt;
&lt;img src="https://readerunner.wordpress.com/wp-content/uploads/2024/04/cover.png?w=625"&gt;&lt;figcaption&gt;Figure 10: Using a TrackedTgraph for drawing&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;7. Other Reading&lt;/h2&gt;
&lt;p&gt;Previous related blogs are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2021/03/20/diagrams-for-penrose-tiles/"&gt;Diagrams for Penrose Tiles&lt;/a&gt; – the first blog introduced drawing &lt;code&gt;Piece&lt;/code&gt;s and &lt;code&gt;Patch&lt;/code&gt;es (without using Tgraphs) and provided a version of decomposing for Patches (&lt;code&gt;decompPatch&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2022/01/06/graphs-kites-and-darts/"&gt;Graphs, Kites and Darts&lt;/a&gt; intoduced Tgraphs. This gave more details of implementation and results of early explorations. (The class &lt;code&gt;Forcible&lt;/code&gt; was introduced subsequently).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2023/04/26/graphs-kites-and-darts-empires-and-superforce/"&gt;Empires and SuperForce&lt;/a&gt; – these new operations were based on observing properties of boundaries of forced Tgraphs.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://readerunner.wordpress.com/2023/09/12/graphs-kites-and-darts-and-theorems/"&gt;Graphs,Kites and Darts and Theorems&lt;/a&gt; established some important results relating &lt;code&gt;force&lt;/code&gt;, &lt;code&gt;compose&lt;/code&gt;, &lt;code&gt;decompose&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</ns0:encoded></item></channel></rss>