Paul Chiusano

Functional programming, UX, tech

TwitterGitHubLinkedInRSS


About my book

My book, Functional Programming in Scala, uses Scala as a vehicle for teaching FP. Read what people are saying about it.


Popular links

Unison: a friendly programming language from the future
unison.cloud: the worldwide elastic computer (coming soon)
Type systems and UX: an example
CSS is unnecessary

The trouble with typeclasses

[   fp   haskell   ]            

Haskell “enforces” typeclass coherence by asking that you define all the instances for a type in the same module (really, file) where you define that type. Whenever you import anything from that module, you bring all these instances into scope. It “works”, but it’s a kludge - when defining the type Foo a, you can’t anticipate (nor are you necessarily aware of) all the instances you might wish to give for Foo. We want an “open universe” where people can after the fact discover common structure and layer it onto existing data types. I feel this is an important property for a language ecosystem.

You can relax things a bit and give “orphan instances” for a type in other modules, but in so doing, you lose typeclass coherence guarantees, and it’s now possible for different parts of your code to use different Foo instances, leading to subtle bugs. Aside: I’d say that most working Haskell programmers make their peace with orphan instances in some cases while feeling a bit dirty.

A workaround that people suggest is to create a newtype around Foo in a separate module, and then give additional instances for this newtype, call it WrappedFoo. This starts to fall apart anytime the type Foo is being embedded in another type. A good example is the class ToJSON a, which is used by Aeson to encode values of type a to JSON. If we have a type Bar [Qux (Int, Foo Blah)] String, and we want to make Bar an instance of ToJSON, we can’t easily use the ToJSON a => ToJSON (WrappedFoo a) instance. The creator of Qux should not need to be aware of JSON at all.

I also dislike this sort of workaround because it’s one of those non-obvious language-specific hacks that I’d be embarrassed to explain to a student. It’s magic (in a bad way) and it doesn’t even work in general.

First-class representation of dictionaries have their own problems:

It seems like we can do better, but I’m not sure how.

comments powered by Disqus