Skip to content

Instantly share code, notes, and snippets.

@ClaireNeveu
Created February 18, 2015 19:47
Show Gist options
  • Save ClaireNeveu/274ef4cec895b61a04a6 to your computer and use it in GitHub Desktop.
Save ClaireNeveu/274ef4cec895b61a04a6 to your computer and use it in GitHub Desktop.
Type Classes Explained

A lot of people have difficulty understanding type-classes​. This has a lot more to do with the context of type-classes than type-classes themselves; Haskell, the foremost language with type-classes, also includes more complicated concepts enabled by type-classes. People often conflate these concepts with type-classes themselves.

Type-classes in Scala are similarly conflated with more complicated concepts and have the added detriment of being a pattern rather than a language feature.

In this post I'll explain type-classes by relating them to somehting everybody understands: the List interface in Java.

public interface List<E> {
   public E get(int index) = ...
   public int size() = ...
   public boolean isEmpty()
   ...
}

public class Array<E> implements List<E> {
   public E get(int index) = ...
   public int size() = ...
   public boolean isEmpty()
   ...
}

The type-class version is almost identical.

class List list where
   get :: list e -> Int -> e
   size :: list e -> Int
   isEmpty :: list e -> Bool
   ...

data Array e = ...

instance List Array where
   get arr index =
   size arr =
   isEmpty arr =
   ...

The only difference is that the implementation of List for Array has been separated from the definition of Array. That is the entire idea of type-classes and how they differ from classic interfaces. This minor difference allows library authors to create new interfaces and implement them for data types in code they don't own, even code in the standard library.

Since we're a Scala shop, here is the equivalent code in Scala:

trait List[L[_]] {
   def get[E](list : L[E], index : Int) : E = ...
   def size[E](list : L[E]) : Int = ...
   def isEmpty[E](list : L[E]) : Boolean = ...
}

class Array[E] {
   ...
}

object Array {
   implicit val arrayListInstance = new List[Array] {
      def get[E](list : L[E], index : Int) : E = ...
      def size[E](list : L[E]) : Int = ...
      def isEmpty[E](list : L[E]) : Boolean = ...
   }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment