-- Leo's gemini proxy

-- Connecting to gemini.thegonz.net:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

Spookless Typeclasses

Everyone else on gemini seems to be doing so at the moment, so I thought I would also give my response to Drew DeVault's article on overloading.

Drew DeVault: Spooky code at a distance


On one hand I agree that this can be horrible, and it's one thing that really put me off C++. On another, a form of overloading is also a feature of Haskell, and in that form I find it entirely non-horrible. So I thought it worth discussing Haskell's approach and what makes it unobjectionable. I am not an expert on any of this.


Typeclasses

In Haskell, the type of the + operator is

(+) :: Num b => b -> b -> b

which can be read as "if b is a type of class Num, then + applied to two instances of b will return an instance of b". Num is a "typeclass", a family of types. You can define a type to be of typeclass Num by giving a definition of + (and some other things). This is a kind of overloading: the definition of + on one type of class Num can be entirely different from that on another.


So why is this less objectionable than the C++ version? I see a few reasons.


1. Instances of typeclasses are often expected to satisfy some laws. In the case of Num and +, any instance of Num is expected to be an abelian group under +. This isn't actually enforced by the compiler (yet!), but such laws are typically documented with the definition of typeclass, and no self-respecting code would break them (certainly not in a library).

1b. There's a (mostly) sensible hierarchy of typeclasses predefined for various mathematical structures, with appropriate laws to go with them, so generally it's clear what class an operation should go in to make it clear to the reader what laws it obeys. (Num actually sits somewhat outside this hierarchy, for historical reasons, but nevermind that.)

2. Haskell is pure, so there's no possibility of side-effects in a definition of +. (Actually this isn't quite true, thanks to unsafePerformIO, but we can ignore that.)

3. You always know what types you're working with in Haskell. Usual convention is to put explicit type signatures on every (top-level, at least) function. When you see "x + y", you generally know what type x and y have (and from the type signature of +, you know they must have the same type). So if you don't already know the definition of + for that type, you look it up. No surprises.


Pithy summary

Typeclasses exorcise overloading.

-- Response ended

-- Page fetched on Thu Apr 25 15:25:52 2024