<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>igstan.ro</title>
    <description>igstan.ro</description>
    <link>http://igstan.ro/</link>
    <atom:link href="http://igstan.ro/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Mon, 08 Aug 2022 12:58:30 +0000</pubDate>
    <lastBuildDate>Mon, 08 Aug 2022 12:58:30 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>Mathematics is a Natural Science</title>
        <description>&lt;p&gt;I believe that mathematics is a science, a natural science to be more precise.
By &lt;em&gt;science&lt;/em&gt; I mean the process or method of distinguishing what&amp;#39;s true from
what&amp;#39;s false and by &lt;em&gt;natural science&lt;/em&gt; I mean the application of science to the
natural world that surrounds us.&lt;/p&gt;

&lt;p&gt;Most people would gladly admit that physics, chemistry and biology are natural
sciences. They study nature in an attempt to find out rules that govern it, to
delineate what&amp;#39;s true from what&amp;#39;s false by means of experiment. The common view
is that what really distinguishes the aforementioned fields from the study from
mathematics is that they use &lt;em&gt;observation&lt;/em&gt;, via experiment, to determine which
theories about the natural world are telling the truth and which are not.&lt;/p&gt;

&lt;p&gt;What I&amp;#39;m trying to argue here is that mathematics is just as much about
experiment and observation of the natural as any other science. The fundamental
difference is that the world described by mathematics is the natural world of
information. And just like physics can have hypotheses which will at some point
be refuted or confirmed (not proved!, more on this later) by experiment, the
same way mathematics presents conjectures which &lt;em&gt;may&lt;/em&gt; at some point be proved
true or false. And just like natural sciences need field scientists and
experimentalists that get their hands dirty and devise and conduct experiments,
the same way mathematicians will conduct experiments in the form of incomplete
or failed proofs, until one of them will actually prove or disprove the
mathematical proposition they set out to study. One salient point here is that
there&amp;#39;s no guarantee that the mathematician may actually find such a proof,
it&amp;#39;s a process of searching that may yield some answer or not — we have
absolutely no guarantee. In a similar vein, the final proof produced by the
mathematician (or even a computer) is actually a natural artefact! It is
embodied in the physical universe and that&amp;#39;s probably true even if the proof
hasn&amp;#39;t escaped the mathematician&amp;#39;s consciousness. And I would argue that even
if consciousness will ultimately turn out not to be an emergent phenomenon of
the physical world, but a thing in itself, it will still be a manifestation of
the &lt;em&gt;natural&lt;/em&gt; world, the world within which we exist. So, yes, a proof is a
natural artefact that we need to discover before we can say with any certainty
if a mathematical statement is either true or false. But that also means that a
mathematical proposition can&amp;#39;t be just true or false, it can also be &amp;quot;unknown
as of yet&amp;quot; — the law of the excluded middle.&lt;/p&gt;

&lt;p&gt;There is however something quite different between mathematics and the other
natural sciences. Mathematics is free to choose some axioms and run wild with
them. Every mathematical fact is contingent on those axioms — assuming the
axioms, such and such is true or false. But the other sciences don&amp;#39;t have this
luxury; they can&amp;#39;t get to decide what are the axioms of the universe, they must
&lt;em&gt;assume&lt;/em&gt;. This small difference has interesting repercussions, one being that
mathematics can &lt;em&gt;prove&lt;/em&gt; things to be true, whereas the other sciences can only
prove things to be false. Here, by &amp;quot;things&amp;quot; I actually mean universal
statements, of the form &amp;quot;for all X&amp;quot;, and not existential statements such as
&amp;quot;there is X&amp;quot;. The best the &amp;quot;classical&amp;quot; sciences can do is prove a universal
statement false, but they have no hope of proving it true, because there&amp;#39;s no
way to be sure that we have taken into account all the axioms of the universe —
there may be laws and situations that could render our beautiful universal
equations false in a blink.&lt;/p&gt;

&lt;p&gt;Mathematics has the luxury of saying: these are our axioms, our atoms and
fundamental forces and everything derives from them. Any theorem or proposition
that assumes more than the given axioms is considered nonsensical. Of course,
one can always explore a new set of axioms to derive new worlds of consequences
based on the respective axioms.&lt;/p&gt;

&lt;p&gt;What really fascinates me here is that these axiom sets are formed &lt;em&gt;within&lt;/em&gt; the
universe. They are not just inventions of our mind, totally detached from what
is outside us — if we can imagine it, it&amp;#39;s natural, it&amp;#39;s part of the universe,
even if that universe is just the world of information. And I think that might
explain the &lt;a href=&quot;https://en.m.wikipedia.org/wiki/The_Unreasonable_Effectiveness_of_Mathematics_in_the_Natural_Sciences&quot;&gt;unreasonable effectiveness of mathematics&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m no mathematician, but even so, during my brief encounters I&amp;#39;ve found myself
wondering how mathematicians could come up with some of their theorems. But it
might not be quite that remarkable if we consider the world of possibilities
engendered by some axioms as a world in itself, a world that the mathematician
is more than happy to explore, to study its every corner, some banal, some not,
or some spuriously so. And because human beings crave order, they might see
patterns and try to generalize them, not much different than what a theoretical
physicist might do, I presume. So they come up with a hypothesis, only they
call it conjecture, and then go on and try to prove it. As noted above, the
endeavour might be fruitful or not, or it might still be ongoing.&lt;/p&gt;

&lt;p&gt;At this point we can try to take a few steps back, maybe a couple parsecs, and
we might not see the two human endeavours as quite so dissimilar — the natural
scientist will take out their magnifier, pencil and pad, explore the world
abord The Beagle and come up with some theory of evolution, while the
mathematician might take out, or not, a pencil and a pad and explore the
curious creatures formed by the atoms of its universe, the axioms. However, at
the end of the day, they will both be searching for structures in their worlds,
for patterns of information, for peculiar connections between the building
blocks of their respective worlds. But these are not isolated worlds, they
share a common home, they&amp;#39;re informational. And both our scientists will use
computation to derive meaning.&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;p&gt;A couple resources for anyone who hasn&amp;#39;t seen them before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cacm.acm.org/magazines/2007/7/5623-computing-is-a-natural-science/fulltext&quot;&gt;Peter J. Denning — Computing is a Natural Science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.scientificamerican.com/article/a-subway-named-turing/&quot;&gt;Ian Stewart — A Subway Named Turing&lt;/a&gt; (I have actually read a version titled &amp;quot;Commuters and Computers: The Intelligent Subway&amp;quot;, which I can&amp;#39;t find online any longer)&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 09 May 2022 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2022-05-09-mathematics-is-a-natural-science.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2022-05-09-mathematics-is-a-natural-science.html</guid>
        
        
      </item>
    
      <item>
        <title>join — My Favorite Unix Command, Probably</title>
        <description>&lt;p&gt;Consider the following case. We have two files storing some data about artists
and their countries of origin:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;$ ls
artists.txt   countries.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are 15 artists and 6 countries:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;$ tail artists.txt countries.txt
==&amp;gt; artists.txt &amp;lt;==
4 Γεωργία Νταγάκη
3 L.E.J
5 Lykke Li
1 Moonlight Breakfast
7 Irina Rimes
2 Jake Bugg
3 ZAZ
8 Lana Del Rey
8 Jackson C. Frank
4 Αλκίνοος Ιωαννίδης

==&amp;gt; countries.txt &amp;lt;==
France 3
Greece 4
Romania 1
Russia 6
Sweden 5
UK 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The two files are related by means of the leading and trailing numbers, which
represent country IDs (made up solely for the purpose of this blog post). Thus
&amp;quot;3 L.E.J&amp;quot; relates to &amp;quot;France 3&amp;quot;, meaning that L.E.J are from France.&lt;/p&gt;

&lt;p&gt;Now, we don&amp;#39;t have a lot of data here, it&amp;#39;s just 15 artists, but it&amp;#39;s already
quite hard to see which artists are from where. If these had been records in a
relational database we could have easily written an SQL &lt;code&gt;INNER JOIN&lt;/code&gt; query to
reveal the associations we&amp;#39;re after:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;artist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;artist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;
 &lt;span class=&quot;k&quot;&gt;WHERE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;artist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;country_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;country&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We could maybe start an SQLite session, create the tables, import the data and
finally execute the query. This may even be a viable approach, but it doesn&amp;#39;t
fit the plan for this blog post. However, if you&amp;#39;re on an Unix system, there&amp;#39;s
a hidden gem of a command, aptly named &lt;code&gt;join&lt;/code&gt;, that can do precisely what the
above SQL query can, only it doesn&amp;#39;t need a database, just regular files. So,
how could we use &lt;code&gt;join&lt;/code&gt; to reproduce the above query?&lt;/p&gt;

&lt;h2&gt;Inner Joins — Where are These Artists From?&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;$ join -t: -22 -o1.2 -o2.1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort         artists.txt   &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort --key&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; countries.txt &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;Moonlight Breakfast:Romania
Adele:UK
Dido:UK
Jake Bugg:UK
Clio:France
Jain:France
L.E.J:France
Stromae:France
ZAZ:France
Γεωργία Νταγάκη:Greece
Αλκίνοος Ιωαννίδης:Greece
Lykke Li:Sweden
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Left Joins - Artists without a Country&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;$ join -a1 -t: -22 -o1.2 -o2.1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort     artists.txt   &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort -k2 countries.txt &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; grep --extended-regexp &lt;span class=&quot;s1&quot;&gt;&amp;#39;:$&amp;#39;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;Irina Rimes:
Jackson C. Frank:
Lana Del Rey:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Right Joins - Countries without Artists&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;$ join -a2 -t: -22 -o1.2 -o2.1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort     artists.txt   &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort -k2 countries.txt &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; grep -E &lt;span class=&quot;s1&quot;&gt;&amp;#39;^:&amp;#39;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;:Russia
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Full Joins — Artists and Countries, Both Unlinked&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;$ join -a1 -a2 -t: -22 -o1.2 -o2.1 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort     artists.txt   &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort -k2 countries.txt &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; grep -E &lt;span class=&quot;s1&quot;&gt;&amp;#39;(^:)|(:$)&amp;#39;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;:Russia
Irina Rimes:
Jackson C. Frank:
Lana Del Rey:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Tabular Display&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;$ join -a1 -a2 -t: -22 -o2.1 -o1.2 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort     artists.tx    &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; sort -k2 countries.txt &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/ /:/&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sed -E &lt;span class=&quot;s1&quot;&gt;&amp;#39;s/^:/𝐍𝐔𝐋𝐋:/; s/:$/:𝐍𝐔𝐋𝐋/&amp;#39;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;  #:COUNTRY:ARTIST&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;===:=======:======&amp;quot;&lt;/span&gt;
      sort -k1 -t: &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; awk -vOFS&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;: &lt;span class=&quot;s1&quot;&gt;&amp;#39;{ print sprintf(&amp;quot;%3d&amp;quot;, NR), $0 }&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; column -ts: &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;  #  COUNTRY  ARTIST
===  =======  ======
  1  France   Clio
  2  France   Jain
  3  France   L.E.J
  4  France   Stromae
  5  France   ZAZ
  6  Greece   Γεωργία Νταγάκη
  7  Greece   Αλκίνοος Ιωαννίδης
  8  Romania  Moonlight Breakfast
  9  Russia   𝐍𝐔𝐋𝐋
 10  Sweden   Lykke Li
 11  UK       Adele
 12  UK       Dido
 13  UK       Jake Bugg
 14  𝐍𝐔𝐋𝐋    Irina Rimes
 15  𝐍𝐔𝐋𝐋    Jackson C. Frank
 16  𝐍𝐔𝐋𝐋    Lana Del Rey
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Refactored&lt;/h2&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Our internal delimiter, needed because the artist names in our records&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# contain spaces. This conflicts with the default separator(s) of all the&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# commands below: spaces or tabs. It should be safe to embed in regexes.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;declare&lt;/span&gt; -r &lt;span class=&quot;nv&quot;&gt;delim&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;:

redelimited&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Replaces the *first* space with our delimiter. This works wonderfully&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# for the datasets we have, but it would fail miserably if added a country&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# whose name contains a whitespace, such as &amp;quot;Sierra Leone&amp;quot;.&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# So... exercise for the reader: handle whitespaces in country names.&lt;/span&gt;
  sed &lt;span class=&quot;s2&quot;&gt;&amp;quot;s/ /&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&amp;quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

sort-by&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  sort -k&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; -t&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

full-join&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  join -a1 -a2 -t&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; -22 -o2.1 -o1.2 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; redelimited artists.txt   &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sort-by &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &amp;lt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; redelimited countries.txt &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sort-by &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

show-nulls&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Prepend/append 𝐍𝐔𝐋𝐋 to rows starting/ending with our delimiter.&lt;/span&gt;
  sed -E &lt;span class=&quot;s2&quot;&gt;&amp;quot;s/^(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)/𝐍𝐔𝐋𝐋\1/; s/(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;)&lt;/span&gt;$&lt;span class=&quot;s2&quot;&gt;/\1𝐍𝐔𝐋𝐋/&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

headers&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;  #&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;delim&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;COUNTRY&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;delim&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;ARTIST&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;===&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;delim&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=======&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;delim&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;======&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

number-rows&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  awk -vOFS&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;{ print sprintf(&amp;quot;%3d&amp;quot;, NR), $0 }&amp;#39;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

tabulate&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  column -ts&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$delim&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

full-join &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; show-nulls &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; sort-by &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; headers&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; number-rows &lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; tabulate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!-- &lt;div class=&quot;highlight&quot;&gt;
  &lt;pre&gt;&lt;code&gt;  #  COUNTRY  ARTIST
===  =======  ======
  1  France   &lt;a href=&quot;#&quot;&gt;Clio&lt;/a&gt;
  2  France   &lt;a href=&quot;#&quot;&gt;Jain&lt;/a&gt;
  3  France   &lt;a href=&quot;#&quot;&gt;L.E.J&lt;/a&gt;
  4  France   &lt;a href=&quot;#&quot;&gt;Stromae&lt;/a&gt;
  5  France   &lt;a href=&quot;#&quot;&gt;ZAZ&lt;/a&gt;
  6  Greece   &lt;a href=&quot;#&quot;&gt;Γεωργία Νταγάκη&lt;/a&gt;
  7  Greece   &lt;a href=&quot;#&quot;&gt;Αλκίνοος Ιωαννίδης&lt;/a&gt;
  8  Romania  &lt;a href=&quot;#&quot;&gt;Moonlight Breakfast&lt;/a&gt;
  9  Russia   𝐍𝐔𝐋𝐋
 10  Sweden   &lt;a href=&quot;#&quot;&gt;Lykke Li&lt;/a&gt;
 11  UK       &lt;a href=&quot;#&quot;&gt;Adele&lt;/a&gt;
 12  UK       &lt;a href=&quot;#&quot;&gt;Dido&lt;/a&gt;
 13  UK       &lt;a href=&quot;#&quot;&gt;Jake Bugg&lt;/a&gt;
 14  𝐍𝐔𝐋𝐋    &lt;a href=&quot;#&quot;&gt;Irina Rimes&lt;/a&gt;
 15  𝐍𝐔𝐋𝐋    &lt;a href=&quot;#&quot;&gt;Jackson C. Frank&lt;/a&gt;
 16  𝐍𝐔𝐋𝐋    &lt;a href=&quot;#&quot;&gt;Lana Del Rey&lt;/a&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
 --&gt;
</description>
        <pubDate>Fri, 06 May 2022 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2022-05-06-my-favorite-unix-command-probably.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2022-05-06-my-favorite-unix-command-probably.html</guid>
        
        
      </item>
    
      <item>
        <title>Unicode vs UTF-8</title>
        <description>&lt;p&gt;I couldn&amp;#39;t sleep and my mind wandered around, finally reaching a place where I
would explain Unicode to an undefined audience. It was almost an hour of laying
purposeless in bed and the explanation seemed rather nice and short, so I
thought I&amp;#39;d get out of bed and put it down here.&lt;/p&gt;

&lt;h2&gt;Unicode vs UTF-8&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/files/images/unicode-vs-utf-8.png&quot; alt=&quot;Google Search auto-suggests unicode vs utf-8.&quot; width=&quot;670&quot;&gt;&lt;/p&gt;

&lt;p&gt;There was a time when I had no idea what Unicode actually was. All I knew was
that it&amp;#39;s some sort of technology that makes computers understand how to display
my first name, Ionuț. I also heard about UTF-8, which presumably did the same
thing, but better. Naturally, I wondered what was the difference between them. I
remember reading Joel Spolsky&amp;#39;s article &lt;a href=&quot;https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/&quot;&gt;The Absolute Minimum Every Software
Developer Absolutely, Positively Must Know About Unicode and Character Sets&lt;/a&gt;,
but for some reason it didn&amp;#39;t click. This is my take on explaining the
difference, 14 years later.&lt;/p&gt;

&lt;h2&gt;Charsets and Code Points&lt;/h2&gt;

&lt;p&gt;Imagine that we&amp;#39;re gathering all the world&amp;#39;s written chracters that exist or
have ever existed. They would be Latin characters, Arabic, Japanese, emojis or
even &lt;a href=&quot;http://www.klingonwiki.net/En/Unicode&quot;&gt;Klingon&lt;/a&gt; ones. Next, we put all of them in a single big ordered list.
By doing this we implicitly assign each character a number — its index in that
list. This very big list is called a &lt;strong&gt;charset&lt;/strong&gt; and the indeces
are called &lt;strong&gt;code points&lt;/strong&gt;. In other words, a charset is a mapping
from code points to characters.&lt;/p&gt;

&lt;p&gt;The next step is to get all software manufacturers to use this charset. Whenever
thay want to accept or output a certain character in their software packages,
they should be representing them in the computer language using the
corresponding code point of our charset, which is just a number.&lt;/p&gt;

&lt;h2&gt;Encodings&lt;/h2&gt;

&lt;p&gt;Computers, however, don&amp;#39;t directly understand mathematical numbers. What they
can do is interpret sequences of &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt; as numbers. So we need yet another
standard that puts everyone on agreement on how to represent these numbers in
the binary language understood by a computer. This additional transformation is
called an &lt;strong&gt;encoding&lt;/strong&gt;. Put otherwise, an encoding specifies how to
translate code points to sequences of &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;32-bit Encoding&lt;/h3&gt;

&lt;p&gt;Where&amp;#39;s the main difficulty with representing numbers in binary format? It&amp;#39;s in
determining where to stop reading a sequence of bits and &lt;em&gt;then&lt;/em&gt; treat it as a
mathematical number.&lt;/p&gt;

&lt;p&gt;We could use 8 bits, i.e., a byte. However, with 8 bits we can only represent
256 numbers. That&amp;#39;s clearly not enough for all the characters we&amp;#39;ve gathered, we
have more than just 256. What next?&lt;/p&gt;

&lt;p&gt;We can use 16 bits in a row to represent a number. That&amp;#39;s a little better, we
can now represent numbers up to 65535. Should it be enough? Well, it accomodates
all the characters we&amp;#39;ve gathered so far and it allows some future ones. But
just to be safe, let&amp;#39;s use 32 bits in a row to represent numbers. This will
allow our charset to acommodate as many as 4,294,967,296 characters. Done deal,
each character will be represented in the computer code using 32 bits for each
character.&lt;/p&gt;

&lt;h3&gt;16-bit Encoding&lt;/h3&gt;

&lt;p&gt;Are we done yet? Not quite, because the software manufacturers will notice that
their users will mostly use characters that are assigned numbers less than 128,
which means they could fit on 7 bits. Having them represented on 32 bits means a
lot of wasted resources. So we come up with a better encoding, one that requires
just 16 bits to represent a number.&lt;/p&gt;

&lt;p&gt;As we&amp;#39;ve seen above, 16 bits allow us to represent numbers up to 65535. What
shall we do for numbers greater than this one? We can apply a clever little
trick. We can reserve a few 16-bit combinations which used alone don&amp;#39;t encode
any code point, but when seen in pairs are treated as 32-bit numbers. We decide
to reserve 2048 such 16-bit combinations, where 1024 of them can only appear as
the first component of the pair and the other 1024 can only appear as the second
component. These are called &lt;strong&gt;surrogate pairs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This trick means that we&amp;#39;ll be able to represent &lt;code&gt;65536 - 2048 = 63488&lt;/code&gt;
characters using 16-bit numbers and an additional &lt;code&gt;1024 * 1024 = 1048576&lt;/code&gt;
characters using surrogate pairs. It all totals up to 1,112,064 characters. This
is less than the 32-bit encoding, but we&amp;#39;ll decide it&amp;#39;s a good trade-off and
move on. In addition, we&amp;#39;ll also limit the maximum number representable in the
32-bit encoding to that of the 16-bit encoding, to keep things consistent. We&amp;#39;ll
call the first encoding &lt;strong&gt;UTF-32&lt;/strong&gt; and the second one
&lt;strong&gt;UTF-16&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;8-bit Encoding&lt;/h3&gt;

&lt;p&gt;Finally, we figure out there&amp;#39;s an even better way to encode code points less
than 128 using just 8 bits. So we come up with an encoding that uses an
increasing number of 8-bit blocks, i.e., bytes, as we need to represent bigger
numbers. This is also called a variable-length encoding because the number of
bytes used to represent a character varies.&lt;/p&gt;

&lt;p&gt;The main idea behind this encoding is to add a mark at the beginning of the
first byte that says how many bytes the sequence is composed of.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt; Code Point Range | Applicable Bit Sequence
------------------|---------------------------------------
 0 - 127          | 0xxxxxxx
 128 - 2047       | 110xxxxx  10xxxxxx
 2048 - 65535     | 1110xxxx  10xxxxxx  10xxxxxx
 65536 - 1114111  | 11110xxx  10xxxxxx  10xxxxxx  10xxxxxx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, if we want to represent a number between 0 and 127 we can just output a &lt;code&gt;0&lt;/code&gt;
bit followed by the 7 bits that encode the number. For numbers between 128 and
2047 we need two bytes. The first one starts with the &lt;code&gt;110&lt;/code&gt; bit sequence, while
the second with the &lt;code&gt;10&lt;/code&gt; bit sequence. The &lt;code&gt;x&lt;/code&gt; characters can be used to fill in
the bits of the number we want to represent. Similarly for the other two cases.
We&amp;#39;ll call this encoding &lt;strong&gt;UTF-8&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;Quick Glossary&lt;/h2&gt;

&lt;p&gt;To summarize all the things we&amp;#39;ve discussed so far, here&amp;#39;s a quick list of concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;charset&lt;/strong&gt;: a mapping from numbers to characters;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unicode&lt;/strong&gt;: the best such charset we have today;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;code point&lt;/strong&gt;: an index into the charset;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;encoding&lt;/strong&gt;: a recipe describing how to represent code points
as computer bits;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UTF-32&lt;/strong&gt;: encoding where each code point is represented using
32-bit sequences;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UTF-16&lt;/strong&gt;: encoding where code points are represented using
16-bit sequences;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UTF-16 surrogate pairs&lt;/strong&gt;: pairs of 16-bit sequences that are
used to encode code points that don&amp;#39;t fit in a single 16-bit sequence. There
are only 1024 surrogate pairs, i.e., 2048 such 16-bit sequences.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UTF-8&lt;/strong&gt;: encoding where code points can be represented using
a variable number of 8-bit sequences, from 1 to a maximum of 4.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;As you&amp;#39;ve probably understood by now, UTF-8 is just a concrete realization of a
more abstract concept called Unicode, so there&amp;#39;s no point in comparing them.&lt;/p&gt;

&lt;h2&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/&quot;&gt;Joel Spolsky&amp;#39;s article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://unicodebook.readthedocs.io/&quot;&gt;Programming with Unicode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://utf8everywhere.org/&quot;&gt;UTF-8 Everywhere&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cl.cam.ac.uk/%7Emgk25/ucs/utf-8-history.txt&quot;&gt;UTF-8 History&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 06 Jun 2017 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2017-06-06-unicode-vs-utf-8.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2017-06-06-unicode-vs-utf-8.html</guid>
        
        
      </item>
    
      <item>
        <title>A Safe Type-Indexed Set for Standard ML, Errata</title>
        <description>&lt;p&gt;It turns out that my &lt;a href=&quot;/posts/2017-04-08-a-safe-type-indexed-set-for-standard-ml.html&quot;&gt;contraption on how to make a type-indexed set safe in Standard ML&lt;/a&gt; doesn&amp;#39;t actually work. It gives the illusion that the type system will prevent that kind of usage errors, but it actually won&amp;#39;t. You still need discipline. Here&amp;#39;s a very short example that breaks the solution. It&amp;#39;s based on the code that&amp;#39;s available in &lt;a href=&quot;https://gist.github.com/igstan/d2585427d4911cda667d42615fce6eda&quot;&gt;this gist&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;set.sml&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reverseOrd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;   &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverseOrd&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;(* it typechecks... :( *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So, if someone creates their own record, without going through an &lt;code&gt;asRecord&lt;/code&gt; call, then the problem reappears. It can appear even without an &lt;code&gt;asRecord&lt;/code&gt; call if the tagging type isn&amp;#39;t hidden properly, i.e., made opaque via an opaque signature ascription: &lt;code&gt;:&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Is there an actual solution then? I&amp;#39;ve spent some brain cycles thinking about this and my answer so far is that there isn&amp;#39;t. The main, technical reason is that SML provides type generativity only at the functor-level, not at the function-level. Here&amp;#39;s what I mean by this.&lt;/p&gt;

&lt;h2&gt;Type Generativity&lt;/h2&gt;

&lt;p&gt;Functors in SML are generative, which means that exposed opaque types are different between different function invocations. We need a signature first, otherwise we can&amp;#39;t hide the exposed types.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;FOO&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can write a zero argument functor that produces &lt;code&gt;FOO&lt;/code&gt; structures where &lt;code&gt;t&lt;/code&gt; is hidden/opaque due to &lt;code&gt;:&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;functor&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FOO&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&amp;#39;s try to use it now:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;F1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stdIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;17.1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;17.12&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;don&amp;#39;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tycon&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mismatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;nn&quot;&gt;F1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;F2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, this is a type error, the type &lt;code&gt;F1.t&lt;/code&gt; is seen as different from the type &lt;code&gt;F2.t&lt;/code&gt;. This feature, where a functor produces different opaque types with each invocation is called generativity. There&amp;#39;s no way to have non-generative functors in SML.&lt;/p&gt;

&lt;p&gt;Back to the problem. What does generativity have to do with our initial problem? The crux of it is that we need to attach unique types to each ordering function we might come up with and the only way to produce unique types in Standard ML is via generativity, i.e., functors. So we need to pass the ordering function as an argument to some functor and have the functor produce a uniquely typed ordering function.&lt;/p&gt;

&lt;p&gt;In conclusion, if we want typesafe &lt;code&gt;union&lt;/code&gt; operations on sets, we need functors. And thus, my previous blog post is useless. The only thing it helped me with is that I learned a bunch of new stuff. Sorry for the confusion.&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Apr 2017 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2017-04-12-a-safe-type-indexed-set-for-standard-ml-errata.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2017-04-12-a-safe-type-indexed-set-for-standard-ml-errata.html</guid>
        
        
      </item>
    
      <item>
        <title>A Safe Type-Indexed Set for Standard ML</title>
        <description>&lt;h2&gt;Update&lt;/h2&gt;

&lt;p&gt;The solution I present in this post turns out not to be safe. See the &lt;a href=&quot;/posts/2017-04-12-a-safe-type-indexed-set-for-standard-ml-errata.html&quot;&gt;subsequent post&lt;/a&gt; for an explanation. What follows is the original article.&lt;/p&gt;

&lt;p&gt;&lt;hr&gt;&lt;/p&gt;

&lt;p&gt;I recently discovered, while preparing the slides for my &lt;a href=&quot;/posts/2017-04-08-modularity-a-la-ml-slides.html&quot;&gt;Modularity à la ML&lt;/a&gt; talk, a solution to a problem I&amp;#39;ve come across a while ago while implementing a type-indexed set data structure in Standard ML.&lt;/p&gt;

&lt;h2&gt;Functor-Based Data Structures&lt;/h2&gt;

&lt;p&gt;First of all, let&amp;#39;s see how sets are represented in the &lt;a href=&quot;http://www.smlnj.org/doc/smlnj-lib/&quot;&gt;SML/NJ library&lt;/a&gt;, which is what I&amp;#39;ve used initially. The SML/NJ library provides a collection of common data structures and algorithms that aren&amp;#39;t part of the standard Basis library mandated by Standard ML. For set data structures, it exposes an &lt;a href=&quot;http://www.smlnj.org/doc/smlnj-lib/Manual/ord-set.html&quot;&gt;&lt;code&gt;ORD_SET&lt;/code&gt;&lt;/a&gt; signature that&amp;#39;s meant for sets implemented using a predefined ordering on the contained elements (there is support for hash sets, too). Two functors produce structures that satisfy the &lt;code&gt;ORD_SET&lt;/code&gt; signature: &lt;a href=&quot;http://www.smlnj.org/doc/smlnj-lib/Manual/binary-set-fn.html&quot;&gt;&lt;code&gt;BinarySetFn&lt;/code&gt;&lt;/a&gt; and &lt;code&gt;SplaySetFn&lt;/code&gt;. Here&amp;#39;s a sample of using &lt;code&gt;BinarySetFn&lt;/code&gt; with integer elements:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;(*&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * Create an IntSet module by instantiating the BinarySetFn&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     * functor with a structure that provides ordering on integers.&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;     *)&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BinarySetFn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ord_key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;intersection&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;nn&quot;&gt;IntSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set3&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;(* [2, 3] *)&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The problem with this approach is that it&amp;#39;s functor-based, which means that one has to call the &lt;code&gt;BinarySetFn&lt;/code&gt; functor for each and every type of element that they want to put in a set data structure. You want a set of strings? Then you call the &lt;code&gt;BinarySetFn&lt;/code&gt; functor with a structure implementing ordering on strings. You want a set of sets? Same thing: call the functor with an ordering on sets.&lt;/p&gt;

&lt;p&gt;This is annoying because it&amp;#39;s just too verbose and it&amp;#39;s due to the fact that structures are not first-class values. They&amp;#39;re part of the module language of Standard ML, which lives separately from the core language of values. Is there a better way? Maybe.&lt;/p&gt;

&lt;h2&gt;Type-Indexed Data Structures&lt;/h2&gt;

&lt;p&gt;At some point I decided I wanted to play around with a different design for such data structures that was not functor-based. The idea was to pass the ordering function as a parameter to the builder functions of the structures. Here&amp;#39;s what I mean by that. The current &lt;code&gt;ORD_SET&lt;/code&gt; signature looks similar to this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ORD_KEY&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ord_key&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord_key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORD_KEY&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ord_key&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;singleton&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So the ordering function is part of a sub-structure of the signature: &lt;code&gt;ORD_KEY&lt;/code&gt;. What if instead we&amp;#39;d do this and eliminate the &lt;code&gt;ORD_KEY&lt;/code&gt; signature entirely?&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;set&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;singleton&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, the two &amp;quot;factory&amp;quot; functions will take a polymorphic ordering as an argument. The type parameter &lt;code&gt;&amp;#39;a&lt;/code&gt; will be the type of set elements. Presumably this ordering function will be stored inside a data structure that implements that abstract &lt;code&gt;set&lt;/code&gt; type. Let&amp;#39;s see how this could look like with a naive list-based set.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;singleton&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The set is represented using a record that stores the elements as a list, together with the ordering function for those elements. We can now add a couple other functions for inserting elements into an existing set and for obtaining the list representation back, which is now held hidden.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;(* continued *)&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;(* continued *)&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I won&amp;#39;t go in detail over the implementation of &lt;code&gt;insert&lt;/code&gt;, but, in short, what it does is that it keeps the elements list sorted so that it&amp;#39;s easier to find whether an element already exists in the list. It&amp;#39;s still naive for a real set implementation that will most likely use a balanced tree, but it&amp;#39;ll do. Let&amp;#39;s now see how to use it:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;intSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;strSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intSet&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;(* [1, 2] *)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strSet&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stdIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;16.1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;16.24&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;don&amp;#39;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;overload&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;strSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intSet&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stdIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.10&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;don&amp;#39;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tycon&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mismatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;intSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;

&lt;p&gt;As you can see, we didn&amp;#39;t have to instantiate any functors here. The set is polymorphic just like a normal list and it&amp;#39;s typesafe — one cannot put a string inside an int set or vice-versa. This is nice, but we&amp;#39;re just about to hit the actual problem. Let&amp;#39;s think how we would go about implementing a common set operation: &lt;code&gt;union&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;(* continued *)&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;(* continued *)&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;not implemented&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I&amp;#39;m not going to fill in the actual implementation because what we have is enough to illustrate the problem. The issue we&amp;#39;re facing is that we have two sets, each providing its own &lt;code&gt;compare&lt;/code&gt; function and there&amp;#39;s absolutely no guarantee that these two functions behave the same. For example, the following code typechecks, but it should&amp;#39;t, because we&amp;#39;re trying to merge sets with different orderings:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reverseOrd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reverseOrd&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;(* shouldn&amp;#39;t compile, but it does *)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The same problem can manifest when the ordering function isn&amp;#39;t stored as part of the set representation, but it&amp;#39;s instead passed as an extra argument to each of the set operations, either explicitly or implicitly, i.e., using type-classes. It&amp;#39;s actually even more hideous in that case because it creates problems even for the &lt;code&gt;insert&lt;/code&gt; operation (imagine two insert calls on the same set instance, but supplying different orderings to each call). This is a problem that can appear in Scala, for example, whose type-class emulation does not guarantee coherence, i.e., a given type can only have a single associated instance of a particular type-class.&lt;/p&gt;

&lt;p&gt;So, is there a solution to this problem in SML? Initially I thought there isn&amp;#39;t, but a few days ago I realized there might be one, albeit not that simple.&lt;/p&gt;

&lt;h2&gt;The Solution&lt;/h2&gt;

&lt;p&gt;To recap, the problem appears for this call, where we can&amp;#39;t statically guarantee that the two set instances carry the same ordering:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One idea of ensuring this property is to somehow tag the orderings through the type system; associate each ordering function with a unique type. We can achive this by wrapping an ordering function in a structure that opaquely exposes the type of the function. And two opaque types are equal only if they&amp;#39;re part of the same signature. So, the first step towards opaque types is a signature, which will let us hide the type in the structure(s):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This looks exactly as the &lt;code&gt;ORD_KEY&lt;/code&gt; signature defined by the SML/NJ library, but we&amp;#39;re not done yet. Let&amp;#39;s try to use it in a way that wasn&amp;#39;t meant to be:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice the &lt;code&gt;:&amp;gt;&lt;/code&gt; part where we&amp;#39;re specifying that the structure must comply with the signature. The difference between &lt;code&gt;:&lt;/code&gt; and &lt;code&gt;:&amp;gt;&lt;/code&gt; is that &lt;code&gt;:&amp;gt;&lt;/code&gt; will keep the representation of types hidden. In our particular case, it renders the &lt;code&gt;IntOrd&lt;/code&gt; structure useless. We cannot use it at all:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stdIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;35.1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;35.22&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;don&amp;#39;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;overload&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This says that &lt;code&gt;IntOrd.compare&lt;/code&gt; only accepts types &lt;code&gt;IntOrd.t&lt;/code&gt;, not &lt;code&gt;int&lt;/code&gt;. We know they&amp;#39;re the same, but the compiler does not because of the opaque signature ascription &lt;code&gt;:&amp;gt;&lt;/code&gt;. What&amp;#39;s to do? We need to add a new function to the signature that will let us lift &lt;code&gt;int&lt;/code&gt; values to &lt;code&gt;IntOrd.t&lt;/code&gt; values:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can now order integers again:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What the &lt;code&gt;TAGGED_ORD.t&lt;/code&gt; represents now is basically the singleton type of the compare function defined in the structure. There will be no other type that will be equal to it, except itself.&lt;/p&gt;

&lt;p&gt;We&amp;#39;re still missing a thing, however. The type-indexed &lt;code&gt;ListSet&lt;/code&gt; module will now need not only a &lt;code&gt;compare&lt;/code&gt; function, but also a &lt;code&gt;wrap&lt;/code&gt; function. And because modules aren&amp;#39;t first-class values in Standard ML, we cannot pass our &lt;code&gt;TAGGED_ORD&lt;/code&gt; structures to the &lt;code&gt;ListSet.empty&lt;/code&gt; function. We need a way to pack those two functions together in a record and pass that instead. So, our final &lt;code&gt;TAGGED_ORD&lt;/code&gt; signature looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;a&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;asRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Notice that we had to introduce another type, &lt;code&gt;a&lt;/code&gt;, that will represent the type of values we&amp;#39;re lifting from. Now &lt;code&gt;IntOrd&lt;/code&gt; becomes this (notice that the &lt;code&gt;a&lt;/code&gt; type is exposed, but &lt;code&gt;t&lt;/code&gt; is not, through what it&amp;#39;s called a translucent signature ascription):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;asRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We&amp;#39;re now finally ready to change our &lt;code&gt;ORD_SET&lt;/code&gt; signature and &lt;code&gt;ListSet&lt;/code&gt; structure to work with this new type of &amp;quot;tagged&amp;quot; orderings:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;sig&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;set&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;singleton&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;&amp;#39;ord_t&lt;/code&gt; type parameter in &lt;code&gt;type (&amp;#39;a, &amp;#39;ord_t) set&lt;/code&gt; represents the unique type associated with a &lt;code&gt;wrap&lt;/code&gt;/&lt;code&gt;compare&lt;/code&gt; record. So the set type isn&amp;#39;t indexed only on the type of the containing elements, but also on the type of the ordering function. This new type parameter will ensure the type safety we&amp;#39;re after.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s how the &lt;code&gt;ListSet&lt;/code&gt; structure needs to change now:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ORD_SET&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;&amp;#39;ord_t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;order&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;singleton&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toList&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;insert&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
          &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
              &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;::&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loop&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elems2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Fail&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;not implemented&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The most important difference is in the &lt;code&gt;insert&lt;/code&gt; function, where we need to call &lt;code&gt;wrap&lt;/code&gt; on the elements that we want to pass to &lt;code&gt;compare&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The same thing would have to happen in the implementation of &lt;code&gt;union&lt;/code&gt; as well, but we don&amp;#39;t have one yet. All we&amp;#39;re interested in is whether illegal calls are refused by the type checker. To check that, let&amp;#39;s define yet another ordering on integers, a reverse ordering:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;structure&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;RevIntOrd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAGGED_ORD&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;struct&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;int&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reverseOrd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;of&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EQUAL&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GREATER&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LESS&lt;/span&gt;

    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverseOrd&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;asRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we can verify whether we can union two sets based on different orderings:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sml&quot; data-lang=&quot;sml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;empty&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;RevIntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;set2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;RevIntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stdIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;110.1&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;110.24&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;operand&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;don&amp;#39;t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;agree&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tycon&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mismatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operator&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;IntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;operand&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;RevIntOrd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;ListSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;union&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;set2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;-&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Success! Another illegal state made unrepresentable! Also, notice how the error message lets us know that we&amp;#39;ve been trying to use difference orderings (&lt;code&gt;IntOrd.t&lt;/code&gt; vs &lt;code&gt;RevIntOrd.t&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;&lt;/span&gt;  operator domain: (a,IntOrd.t) ListSet.set
  operand:         (a,RevIntOrd.t) ListSet.set
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That&amp;#39;s all, folks! You can find the final version of the code in this &lt;a href=&quot;https://gist.github.com/igstan/d2585427d4911cda667d42615fce6eda&quot;&gt;gist&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sat, 08 Apr 2017 03:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2017-04-08-a-safe-type-indexed-set-for-standard-ml.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2017-04-08-a-safe-type-indexed-set-for-standard-ml.html</guid>
        
        
      </item>
    
      <item>
        <title>Modularity à la ML (slides)</title>
        <description>&lt;p&gt;A few words regarding modularity in Standard ML and Scala. These are the slides
for the presentation I held yesterday as part of Scalar Conf 2017, Warsaw,
Poland.&lt;/p&gt;

&lt;script async class=&quot;speakerdeck-embed&quot; data-id=&quot;467810402fbf4347a7d9c118963fa623&quot; data-ratio=&quot;1.33333333333333&quot; src=&quot;//speakerdeck.com/assets/embed.js&quot;&gt;&lt;/script&gt;
</description>
        <pubDate>Sat, 08 Apr 2017 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2017-04-08-modularity-a-la-ml-slides.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2017-04-08-modularity-a-la-ml-slides.html</guid>
        
        
      </item>
    
      <item>
        <title>On Determinism and Free Will</title>
        <description>&lt;p&gt;For the past two or three weeks I&amp;#39;ve been somehow obsessed with the idea that there&amp;#39;s no free will, that humans possess no free will. This idea didn&amp;#39;t just pop up in my head, it&amp;#39;s the result of all the other ideas I&amp;#39;ve heard or read before. This time it clicked, though, and it clicked so hard that I feel I&amp;#39;m in the midst of an existential crisis. In high-school it was whether there&amp;#39;s any purpose in life and I managed to overcome that one quite easily in retrospect. Now it&amp;#39;s harder, but maybe there&amp;#39;s nothing I can do about it, as I shall explain immediately. What follows is mostly a brain dump in an attempt to defuse my head.&lt;/p&gt;

&lt;h2&gt;Determinism vs Free Will&lt;/h2&gt;

&lt;p&gt;My current belief is that the universe is a deterministic entity, that the present is entirely determined by its past, that the past is determined by its past and so on, until the beginning of time. I&amp;#39;m also reticent of believing that there&amp;#39;s anything else &amp;quot;outside&amp;quot; the universe, for example a God, heaven, angels and so on, although I kind of wish it were true.&lt;/p&gt;

&lt;p&gt;Now, if the universe is all there is to it and we&amp;#39;re also part of the universe, our minds included, then it must be that all that we feel we are is a deterministic result of the initial conditions of the universe. Every thought we had, have or will have can virtually be traced back to the beginning of the universe. Every decision we make, every action we take is a result of a previous configuration of the universe we&amp;#39;re occupying. Where&amp;#39;s free will then? Whose free will even?&lt;/p&gt;

&lt;p&gt;It seems that the &lt;em&gt;feeling&lt;/em&gt; of free will is one of those traits that natural selection has favored, but which bear no actual relation to the reality. We think we have free will because otherwise we&amp;#39;d get depressed and we&amp;#39;d commit suicide, I presume.&lt;/p&gt;

&lt;p&gt;However, it gets meta. I believe these thoughts I&amp;#39;ve put down here were meant to exist from the very beginning of time. There&amp;#39;s no contribution of any entity to anything. The particles I&amp;#39;m made of are now in a state that can influence other particles into some other states and them, in turn, influence others, i.e., any reader of this. A continuous movement of star dust in the universe, but certain clumps form our selves. Or rather, form machines complex enough to build a certain, most likely imprecise model of themselves, a model that sees the machine as having a special sauce — consciousness.&lt;/p&gt;

&lt;p&gt;As with anything in this universe, my thoughts are bound to evolve over time. I might read about some discovery or opinion that will change how I see things right now. But will these thoughts change me at this moment? Technically, they won&amp;#39;t cause anything to happen that wasn&amp;#39;t meant to happen. Whether I&amp;#39;ll decide to ignore them completely or get depressed, it was meant to be that way.&lt;/p&gt;

&lt;p&gt;These aren&amp;#39;t new thoughts, of course. There have been many more before me that have thought of this problem, but it&amp;#39;s still an open one. It&amp;#39;s called the free will problem and appears because there seems to be an incompatibility between determinism and free will. One quote that resonates with me, &lt;a href=&quot;https://en.wikipedia.org/wiki/Compatibilism#Defining_free_will&quot;&gt;attributed by Wikipedia to Arthur Schopenhaur&lt;/a&gt; reads:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Man can do what he wills but he cannot will what he wills.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;Atheists vs Free Will&lt;/h2&gt;

&lt;p&gt;A few years ago I had a small argument with a work colleague where I argued that what a person can achieve in life is limited by the biological substrate, to which he disagreed. At the time I didn&amp;#39;t completely realized the conflict between determinism and free will. What really surprised me about that discussion was when my colleague said that I have a religious view of the world. A deterministic existence would be one where God dictates what you can or cannot do, whereas an existence where free will existed didn&amp;#39;t require a God. It struck me as totally paradoxical. To me, free will requires something outside the universe, like a God or a soul, but a deterministic, machine-like existence doesn&amp;#39;t require a God.&lt;/p&gt;

&lt;p&gt;The reason I&amp;#39;ve recounted this is because I&amp;#39;ve recently come across a &lt;a href=&quot;https://www.youtube.com/watch?v=2L1a7CHYVLg&quot;&gt;video&lt;/a&gt; where someone says basically the same thing — as an atheist he believed in free will and thought that only religious people would believe in a deterministic life. Isn&amp;#39;t it ironic? It is to me.&lt;/p&gt;

&lt;h2&gt;I, Robot&lt;/h2&gt;

&lt;p&gt;You know, some movies related to artificial intelligence, the strong one, raise questions on how a robot might feel if it finds out that it&amp;#39;s just a robot, that it&amp;#39;s not the &lt;em&gt;real thing&lt;/em&gt;. I&amp;#39;d like to see a movie where human beings realize that they&amp;#39;re less than they think they are — just machines. Maybe someone has made such a film already?&lt;/p&gt;

&lt;p&gt;I normally have a resources section at the end of my blog posts, with links to resources I&amp;#39;ve used while doing my research. I won&amp;#39;t do this now because the research is still in progress and I&amp;#39;m pretty sure you can find them yourself just as easily.&lt;/p&gt;
</description>
        <pubDate>Thu, 05 May 2016 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2016-05-05-on-determinism-and-free-will.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2016-05-05-on-determinism-and-free-will.html</guid>
        
        
      </item>
    
      <item>
        <title>Calculating an Object Graph's Size on the JVM</title>
        <description>&lt;p&gt;Here&amp;#39;s a little something I learned today. Recently, I had the task of adding an
in memory cache for an exchange rate web service to the project I&amp;#39;m working on.
I&amp;#39;ve used Guava&amp;#39;s &lt;code&gt;CacheBuilder&lt;/code&gt; and set some random values for its maximum size
and expiry periods. And the I got wondering, what would be the amount of memory
this cache will need when full?&lt;/p&gt;

&lt;p&gt;I had a faint idea, from Twitter, that a tool called &lt;a href=&quot;http://openjdk.java.net/projects/code-tools/jol/&quot;&gt;jol (Java Object Layout)&lt;/a&gt;
might be exactly what I needed, but I wasn&amp;#39;t exactly sure. I investigated and,
sure enough, it is a very good tool for finding not only the memory size of an
object graph, but also how objects are laid out in memory on different JVMs. This
later feature is useful when optimizing for CPU caches, but I&amp;#39;ve got no experience
with this yet.&lt;/p&gt;

&lt;p&gt;Back to the subject of this blog post — finding the total amount of memory for
an object graph — things are actually quite simple.&lt;/p&gt;

&lt;h2&gt;Add Dependency&lt;/h2&gt;

&lt;p&gt;First, you want to add jol as a dependency in your favourite build system. I&amp;#39;m
using sbt here.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;libraryDependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;org.openjdk.jol&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;jol-core&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;1.0-SNAPSHOT&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;compile&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you may have noticed, I&amp;#39;ve declared this dependency as compile time only. We
need it during interactive development, but not (yet) at runtime.&lt;/p&gt;

&lt;h2&gt;Start Exploring&lt;/h2&gt;

&lt;p&gt;Next, fire up &lt;code&gt;sbt console&lt;/code&gt; and try these commands:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.openjdk.jol.info.GraphLayout&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GraphLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parseInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;USD&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toFootprint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GraphLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parseInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;USD&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toPrintable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GraphLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parseInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;USD&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;EUR&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;totalSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here&amp;#39;s the output I got when inspecting a simple tuple value.&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
scala&amp;gt; println(GraphLayout.parseInstance(&quot;USD&quot; -&amp;gt; &quot;EUR&quot;).toFootprint)
scala.Tuple2 instance footprint:
 COUNT   AVG   SUM DESCRIPTION
     2    24    48 [C
     2    24    48 java.lang.String
     1    24    24 scala.Tuple2
     5         120 (total)
&lt;/pre&gt;

&lt;p&gt;In the first column we have an instance count per class: two instances of type
&lt;code&gt;[C&lt;/code&gt; or &lt;code&gt;Array[Char]&lt;/code&gt;, two instance of type &lt;code&gt;String&lt;/code&gt; and one instance of type
&lt;code&gt;Tuple2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The third column shows how much memory all the instance of a particular type
occupy. The char arrays and the strings occupy 48 bytes each. The tuple takes
24 bytes. They all add up to a total memory size of 120 bytes.&lt;/p&gt;

&lt;p&gt;The average column says what amount of memory is consumed, on average, by each
instance. Why on average though? I don&amp;#39;t have an answer to this yet, but I
presume is becuse of byte alignment rules.&lt;/p&gt;

&lt;p&gt;Another question might be why does a single &lt;code&gt;String&lt;/code&gt; instance occupy 24 bytes?
This is where another utility, called &lt;code&gt;ClassLayout&lt;/code&gt; comes in handy:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
scala&amp;gt; println(ClassLayout.parseClass(classOf[String]).toPrintable)
java.lang.String object internals:
 OFFSET  SIZE   TYPE DESCRIPTION                    VALUE
      0    12        (object header)                N/A
     12     4 char[] String.value                   N/A
     16     4    int String.hash                    N/A
     20     4    int String.hash32                  N/A
Instance size: 24 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
&lt;/pre&gt;

&lt;p&gt;The output says precisely how the object fields will be lay out in the computer
memory and how much space they take up.&lt;/p&gt;

&lt;p&gt;The first item, the object header, contains class type information. It starts
at offset 0 and takes up 12 bytes.&lt;/p&gt;

&lt;p&gt;The second item is the first object field. In this case we have an array of
chars, which is used to store the actual characters that make up the string.
It starts at offset 12 and occupies 4 bytes. Similar for the subsequent two
fields.&lt;/p&gt;

&lt;p&gt;If you&amp;#39;d like to know more, the &lt;a href=&quot;http://hg.openjdk.java.net/code-tools/jol&quot;&gt;project&amp;#39;s source tree&lt;/a&gt; contains a directory
of samples demonstrating some of its features. It&amp;#39;s a good place to learn more
about jol.&lt;/p&gt;

&lt;h2&gt;References&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;jol — &lt;a href=&quot;http://openjdk.java.net/projects/code-tools/jol/&quot;&gt;http://openjdk.java.net/projects/code-tools/jol/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://psy-lob-saw.blogspot.ro/2014/03/java-object-layout-tale-of-confusion.html&quot;&gt;Java Object Layout: A Tale Of Confusion &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bboniao.com/openjdk/2014-06/java-object-layoutjol.html&quot;&gt;http://bboniao.com/openjdk/2014-06/java-object-layoutjol.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Tue, 23 Sep 2014 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2014-09-23-calculating-an-object-graphs-size-on-the-jvm.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2014-09-23-calculating-an-object-graphs-size-on-the-jvm.html</guid>
        
        
        <category>jvm</category>
        
      </item>
    
      <item>
        <title>Run a single specs2 example from sbt</title>
        <description>&lt;p&gt;Every now and then I need to run an single failing specs2 test from the sbt
command line. Because it happens so seldom, though, I keep on forgetting how to
do it. Google isn&amp;#39;t very helpful either because I have to remember the specs2
terminology, i.e., specification vs example, when searching.&lt;/p&gt;

&lt;p&gt;In this blog post I&amp;#39;ll work with the following test:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.example.quux&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.specs2.mutable._&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// This class represents a **specification**.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ExampleSpec&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Specification&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;quot;this is a group of example&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;quot;this is example one&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;must&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;s&quot;&gt;&amp;quot;this is example two&amp;quot;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;must&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Running a Single Specification&lt;/h2&gt;

&lt;p&gt;If you&amp;#39;re interested in running all the &lt;em&gt;examples&lt;/em&gt; in the &lt;code&gt;ExampleSpec&lt;/code&gt;
&lt;em&gt;specification&lt;/em&gt;, the following sbt command will do.&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;sbt&amp;gt; testOnly com.example.quux.ExampleSpec&lt;/pre&gt;

&lt;p&gt;Or, using a wildcard for the package name, which is what I personally prefer.&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;sbt&amp;gt; testOnly *ExampleSpec&lt;/pre&gt;

&lt;h2&gt;Running a Single Example&lt;/h2&gt;

&lt;p&gt;If, on the other hand, you&amp;#39;d like to run just the &lt;em&gt;example&lt;/em&gt; named &lt;code&gt;this is
example two&lt;/code&gt;, you have to make use of the &lt;code&gt;-ex&lt;/code&gt; specs2 flag. Please note, this
argument only works with the specs2 testing framework. ScalaTest supports a
different &lt;a href=&quot;http://www.scalatest.org/user_guide/using_the_runner&quot;&gt;set of arguments&lt;/a&gt;.&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;sbt&amp;gt; testOnly -- -ex &quot;this is example two&quot;&lt;/pre&gt;

&lt;p&gt;This works, but the test reporter will show even the names of the groups that
haven&amp;#39;t been run, which makes it hard to figure out where&amp;#39;s the actual failed
test. For this reason, the command I&amp;#39;m actually using is akin to this one:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;sbt&amp;gt; testOnly *ExampleSpec -- -ex &quot;this is example two&quot;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt;: you have to wrap the example name in double quotes. Single quotes won&amp;#39;t
do it.&lt;/p&gt;
</description>
        <pubDate>Wed, 13 Aug 2014 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2014-08-13-run-a-single-specs2-example-from-sbt.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2014-08-13-run-a-single-specs2-example-from-sbt.html</guid>
        
        
      </item>
    
      <item>
        <title>Contravariant Functors — An Intuition</title>
        <description>&lt;p&gt;Today I came across a &lt;a href=&quot;http://tmorris.net/posts/functors-and-things-using-scala/index.html&quot;&gt;blog post listing different types of functors&lt;/a&gt; (expressed
using Scala), and once again I found a mention of contravariant functors. I
heard about them in the past, saw their signature, but... no epiphany.&lt;/p&gt;

&lt;p&gt;In this post I&amp;#39;d like to gain an intution for what a contravariant functor is.
I&amp;#39;ll leave it for another post to understand the other scary one, the exponential
functor (shouldn&amp;#39;t be much harder I presume, seems to be composed of two other
functors — one covariant, the other contravariant).&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s the signature given for contravariant functor in the above blog post:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Contravariant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contramap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It&amp;#39;s pretty mind bending (for me) to understand how that &lt;code&gt;f&lt;/code&gt; function can possibly
get a handle over a value of type &lt;code&gt;B&lt;/code&gt; when &lt;code&gt;B&lt;/code&gt; can&amp;#39;t be found in the argument list,
only in the return type (as opposed to &lt;code&gt;A&lt;/code&gt;). What&amp;#39;s going on then?&lt;/p&gt;

&lt;h2&gt;A Concrete Example&lt;/h2&gt;

&lt;p&gt;After a brief search on the internet I found out that a good example of a
contravariant functor can actually be seen in the Scala standard library.
&lt;a href=&quot;https://github.com/scala/scala/blob/v2.10.3/src/library/scala/math/Ordering.scala#L218&quot;&gt;&lt;code&gt;Ordering.by&lt;/code&gt;&lt;/a&gt; is a &lt;code&gt;contramap&lt;/code&gt; incarnation, specialized for instances of
&lt;code&gt;Ordering&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The signature looks a bit different that the one used by Tony Morris, but they&amp;#39;re
the same conceptually (the former is just more general). What it says is that if
you know how to compare elements of type &lt;code&gt;S&lt;/code&gt; and you have a function relating
elements of type &lt;code&gt;T&lt;/code&gt; to elements of type &lt;code&gt;S&lt;/code&gt;, then you know how to compare elements
of type &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are two conceptual mappings here. At a higher-level you want to map
&lt;code&gt;Ordering[S]&lt;/code&gt; to &lt;code&gt;Ordering[T]&lt;/code&gt;, but in order to achieve that an opposite mapping
is required — from &lt;code&gt;T&lt;/code&gt; to &lt;code&gt;S&lt;/code&gt; — hence &amp;quot;contra&amp;quot;.&lt;/p&gt;

&lt;p&gt;Generalizing we get that &lt;code&gt;contramap&lt;/code&gt; is a function which says that if you give
it some abstraction over a concept &lt;code&gt;A&lt;/code&gt;, i.e., &lt;code&gt;F[A]&lt;/code&gt;, and a function that maps
from a different concept &lt;code&gt;B&lt;/code&gt; to the concept &lt;code&gt;A&lt;/code&gt;, then it is able to give you back
an abstraction over &lt;code&gt;B&lt;/code&gt;, i.e., &lt;code&gt;F[B]&lt;/code&gt;. Pretty abstract maybe, but bear with me.&lt;/p&gt;

&lt;h2&gt;Intuition&lt;/h2&gt;

&lt;p&gt;Here&amp;#39;s a simple real world example inspired by &lt;a href=&quot;http://www.scala-lang.org/old/node/3819.html&quot;&gt;this thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Everybody knows how to compare numbers, right? 2 is smaller than 3, 3 is greater
than 2. Also, everybody knows what money are. It&amp;#39;s a concept we&amp;#39;ve been using for
ages now, and it&amp;#39;s pretty trivial to draw a correspondence between money and
numbers. We&amp;#39;d map a one dollar bill (100 cents) to the number 100 for example.&lt;/p&gt;

&lt;p&gt;Because we know these two things: 1. how to compare numbers; 2. how to map from
money to numbers, we can actually compare money. Obvious, right? Well, calling
&lt;code&gt;contramap&lt;/code&gt; using those two facts as arguments will provide you the knowledge of
how to compare money. That&amp;#39;s exactly the knowledge that a contravariant functor
encodes, but in a more general way, not only for numbers, money and comparisons.&lt;/p&gt;

&lt;p&gt;As I said, the final goal is to actually map &lt;code&gt;F[A] =&amp;gt; F[B]&lt;/code&gt;, but in order to
achieve that we need a function that maps &lt;code&gt;B =&amp;gt; A&lt;/code&gt;, i.e. the opposite (contra)
direction. It&amp;#39;s basic abstraction. You build new abstraction out of old ones by
specifying relationships between concepts.&lt;/p&gt;

&lt;h2&gt;Translating to Scala&lt;/h2&gt;

&lt;p&gt;Let&amp;#39;s put the above example in Scala code. First, let&amp;#39;s represent &lt;code&gt;Money&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Scala already knows how to compare &lt;code&gt;Int&lt;/code&gt;s and based on that knowledge we want to
specify how &lt;code&gt;Money&lt;/code&gt; should be compared, i.e., derive &lt;code&gt;Ordering[Money]&lt;/code&gt; from
&lt;code&gt;Ordering[Int]&lt;/code&gt;. To achieve that, we need a way to specify which sub-component
of &lt;code&gt;Money&lt;/code&gt; is our desired &lt;code&gt;Int&lt;/code&gt;, which is trivial in this example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contramapFn&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Money&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Having defined that, and given that an implicit instance for &lt;code&gt;Ordering[Int]&lt;/code&gt; is
already in scope, all we need now is to call the &lt;code&gt;contramap&lt;/code&gt; function defined on
the &lt;code&gt;Ordering&lt;/code&gt; object, namely, the &lt;code&gt;by&lt;/code&gt; method. The resulted &lt;code&gt;Ordering[Money]&lt;/code&gt;
is marked as being implicit because we want the compiler to use it when we use
the comparison method &lt;code&gt;&amp;lt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;moneyOrd&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contramapFn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can easily compare &lt;code&gt;Money&lt;/code&gt; instances (we still need an implicit conversion
from &lt;code&gt;Ordering&lt;/code&gt; to &lt;code&gt;Ordered&lt;/code&gt; in scope, hence the first import):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scala.math.Ordered._&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scala.math.Ordered._&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;res0&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;scala&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Money&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;res1&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Boolean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Implementing &lt;code&gt;by&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;How is &lt;code&gt;Ordering.by&lt;/code&gt; implemented though? One possible implementation looks like
this (the &lt;a href=&quot;https://github.com/scala/scala/blob/v2.10.3/src/library/scala/math/Ordering.scala#L218&quot;&gt;real one&lt;/a&gt; is a bit more complicated due to optimizations):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scala&quot; data-lang=&quot;scala&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;implicit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Ordering&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As you can see, it creates an &lt;code&gt;Ordering&lt;/code&gt; instance whose &lt;code&gt;compare&lt;/code&gt; method simply
delegates to the &lt;code&gt;compare&lt;/code&gt; method of the known &lt;code&gt;Ordering[S]&lt;/code&gt;, but &lt;strong&gt;not before&lt;/strong&gt;
transforming the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; parameters by passing them through &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This simple implementation also gives an idea of how &lt;code&gt;f&lt;/code&gt; is able to receive an
argument of type &lt;code&gt;T&lt;/code&gt;. It creates a new &amp;quot;function&amp;quot; that will receive &lt;code&gt;T&lt;/code&gt;s and
inside that &amp;quot;function&amp;quot; will we have access to these &lt;code&gt;T&lt;/code&gt;s to pass to &lt;code&gt;f&lt;/code&gt;. When you
need a value of a specific type and you don&amp;#39;t have it, what do you do? You return
a function that asks for one. In this particular case we don&amp;#39;t have a proper
function, but an object (an instance of &lt;code&gt;Ordering&lt;/code&gt;), which is nothing more than
a collection of functions, so the reasoning holds.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There are a few more concrete implementation of contravariant functors in the
pages I&amp;#39;ve linked to in the &lt;a href=&quot;#resources&quot;&gt;resources section&lt;/a&gt; below, but the
principle remains the same — you build new abstractions out of old ones by
providing a mapping function from the new concept being abstracted to the old
one that has already been abstracted.&lt;/p&gt;

&lt;h2&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://tmorris.net/posts/functors-and-things-using-scala/index.html&quot;&gt;Functors and things using Scala&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fpcomplete.com/school/to-infinity-and-beyond/pick-of-the-week/profunctors&quot;&gt;I love profunctors. They&amp;#39;re so easy.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://hackage.haskell.org/package/contravariant-0.4.4/docs/Data-Functor-Contravariant.html&quot;&gt;Contravariant functors package&lt;/a&gt; on Hackage&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Thu, 31 Oct 2013 00:00:00 +0000</pubDate>
        <link>http://igstan.ro/posts/2013-10-31-contravariant-functors-an-intuition.html</link>
        <guid isPermaLink="true">http://igstan.ro/posts/2013-10-31-contravariant-functors-an-intuition.html</guid>
        
        
      </item>
    
  </channel>
</rss>
