<h2 id="background">Background</h2>
<p>Type classes are Haskell’s way of doing ad hoc polymorphics or overloading. They are used to defined set of functions that can operate more than one specific type of data.</p>
<h2 id="equality">Equality</h2>
<p>In Haskell there’s no default equality, it has to be defined.</p>
<p>There’s two parts to the puzzle. First is type class <code>Eq</code> that comes with the standard library and defines function signatures for equality and non-equality comparisons. There’s type parameter <code>a</code> in the definition, which is filled by user when they define instance of <code>Eq</code> for their data. In that instance definition, <code>a</code> is filled with concrete type.</p>
<pre><code>class  Eq a where
  (==) :: a -&gt; a -&gt; Bool
  (/=) :: a -&gt; a -&gt; Bool

  x /= y = not (x == y)</code></pre>
<p>Definition above can be read as “class Eq a that has two functions with following signatures and implementations”. In other words, given two <code>a</code>, this function determines are they equal or not (thus <code>Bool</code> as return type). <code>/=</code> is defined in terms of <code>==</code>, so it’s enough to define one and you get other one for free. But you can still define both if you’re so included (maybe some optimization case).</p>
<p>If we define our own <code>Size</code> type, like below, we can compare sizes:</p>
<pre><code>data Size = Small | Medium | Large
    deriving (Show, Read)

instance Eq Size where
    Small == Small = True
    Medium == Medium = True
    Large == Large = True
    _ == _ = False</code></pre>
<p>And here’s couple example comparisons.</p>
<pre><code>&gt; Small == Small
True
&gt; Large /= Large
False</code></pre>
<p>Writing these by hand is both tedious and error prone, so we usually use automatic derivation for them. Note how the second line now reads <code>deriving (Show, Read, Eq)</code>.</p>
<pre><code>data Size = Small | Medium | Large
    deriving (Show, Read, Eq)</code></pre>
<h2 id="hierarchy-between-type-classes">Hierarchy between type classes</h2>
<p>There can be hierarchy between type classes, meaning one requires presence of another. Common example is <code>Ord</code>, which is used to order data.</p>
<pre><code>class Eq a =&gt; Ord a where
    compare :: a -&gt; a -&gt; Ordering
    (&lt;) :: a -&gt; a -&gt; Bool
    (&gt;=) :: a -&gt; a -&gt; Bool
    (&gt;) :: a -&gt; a -&gt; Bool
    (&lt;=) :: a -&gt; a -&gt; Bool
    max :: a -&gt; a -&gt; a
    min :: a -&gt; a -&gt; a</code></pre>
<p>This definition can be read as “class Ord a, where a has instance of Eq, with pile of functions as follows”. <code>Ord</code> has default implementation for quite many of these, in terms of others, so it’s enough to implement either <code>compare</code> or <code>&lt;=</code>.</p>
<p>For our <code>Size</code>, instance of <code>Ord</code> could be defined as:</p>
<pre><code>instance Ord Size where
    Small &lt;= _ = True
    Medium &lt;= Small = False
    Medium &lt;= _ = True
    Large &lt;= Large = True
    Large &lt;= _ = False</code></pre>
<h2 id="writing-generic-code">Writing generic code</h2>
<p>There’s lots and lots of type classes in standard library:</p>
<ul>
<li><code>Num</code> for numeric operations</li>
<li><code>Integral</code> for integer numbers</li>
<li><code>Floating</code> for floating numbers</li>
<li><code>Show</code> for turning data into strings</li>
<li><code>Read</code> for turning strings to data</li>
<li><code>Enum</code> for sequentially ordered types (these can be enumerated)</li>
<li><code>Bounded</code> for things with upper and lower bound</li>
<li>and so on…</li>
</ul>
<p>Type classes allow you to write really generic code. Following is contrived example using <code>Ord</code> and <code>Show</code>:</p>
<pre><code>check :: (Ord a, Show a) =&gt; a -&gt; a -&gt; String
check a b =
    case compare a b of
        LT -&gt;
            show a ++ &quot; is smaller than &quot; ++ show b
        GT -&gt;
            show a ++ &quot; is greater than &quot; ++ show b
        EQ -&gt;
            show a ++ &quot; and &quot; ++ show b ++ &quot; are equal&quot;</code></pre>
<p>Check takes two parameters that are same type and that type has to have <code>Ord</code> and <code>Show</code> instances. <code>Ord</code> is for ordering and <code>Show</code> is for turning data into string (handy for displaying it). The end result is string telling result of comparison. Below is some examples of usage. Note how our function can handle different types of data: <code>Size</code>, <code>Int</code> and <code>[Int]</code>.</p>
<pre><code>&gt; check Medium Small
&quot;Medium is greater than Small&quot;
&gt; check Small Large
&quot;Small is smaller than Large&quot;
&gt; check 7 3
&quot;7 is greater than 3&quot;
&gt; check [1, 2] [1, 1, 1]
&quot;[1, 2] is greater than [1, 1, 1]&quot;</code></pre>
<p>There are many extensions to type classes that add more behaviour. These aren’t part of standard Haskell, but can be enabled with a pragma definition or compiler flag. They can be somewhat more complicated to use, have special cases that need careful consideration, but offer interesting options.</p>
<h2 id="in-closing">In closing</h2>
<p>Thank you for listening. Question, comments and feedback welcome. Best way to catch me nowadays is either by email or in fediverse, where I’m <code>Tuula@mastodon.social</code>.</p>
