# Haskell/Advanced type classes

* Advanced type classes (Solutions)
* Fun with Types
* Polymorphism
* Existentially quantified types
* Advanced type classes
* Phantom types
* Generalised algebraic data-types (GADT)
* Datatype algebra
* Type constructors & Kinds
Type classes may seem innocuous, but research on the subject has resulted in several advancements and generalisations which make them a very powerful tool.

## Multi-parameter type classes

Multi-parameter type classes are a generalisation of the single parameter type classes, and are supported by some Haskell implementations.
Suppose we wanted to create a 'Collection' type class that could be used with a variety of concrete data types, and supports two operations -- 'insert' for adding elements, and 'member' for testing membership. A first attempt might look like this:
Example: The Collection type class (wrong)
This won't compile, however because the arguments to (:) must be of type [a] and a whereas we supply an e. The problem is that the 'e' type variable in the Collection operations comes from nowhere -- there is nothing in the type of an instance of Collection that will tell us what the 'e' actually is, so we can never define implementations of these methods. Multi-parameter type classes solve this by allowing us to put 'e' into the type of the class. Here is an example that compiles and can be used:
Example: The Collection type class (right)

## Functional dependencies

A problem with the above example is that, in this case, we have extra information that the compiler doesn't know, which can lead to false ambiguities and over-generalised function signatures. In this case, we can see intuitively that the type of the collection will always determine the type of the element it contains - so if c is [a], then e will be a. If c is Hashmap a, then e will be a. (The reverse is not true: many different collection types can hold the same element type, so knowing the element type was e.g. Int, would not tell you the collection type).
In order to tell the compiler this information, we add a functional dependency, changing the class declaration to
Example: A functional dependency
A functional dependency is a constraint that we can place on type class parameters. Here, the extra | c -> e should be read 'c uniquely identifies e', meaning for a given c, there will only be one e. You can have more than one functional dependency in a class -- for example you could have c -> e, e -> c in the above case. And you can have more than two parameters in multi-parameter classes.

### Examples
#### Matrices and vectors

Suppose you want to implement some code to perform simple linear algebra:
Example: The Vector and Matrix datatypes
You want these to behave as much like numbers as possible. So you might start by overloading Haskell's Num class:
Example: Instance declarations for Vector and Matrix
The problem comes when you want to start multiplying quantities. You really need a multiplication function which overloads to different types:
Example: What we need
How do we specify a type class which allows all these possibilities?
We could try this:
Example: An ineffective attempt (too general)
That, however, isn't really what we want. As it stands, even a simple expression like this has an ambiguous type unless you supply an additional type declaration on the intermediate expression:
Example: Ambiguities lead to more verbose code
After all, nothing is stopping someone from coming along later and adding another instance:
Example: A nonsensical instance of Mult
The problem is that c shouldn't really be a free type variable. When you know the types of the things that you're multiplying, the result type should be determined from that information alone.
You can express this by specifying a functional dependency:
Example: The correct definition of Mult
This tells Haskell that c is uniquely determined from a and b.
* Advanced type classes
* Solutions to exercises
* Fun with Types
* Polymorphism
* >> Existentially quantified types
* >> Advanced type classes
* >> Phantom types
* >> Generalised algebraic data-types (GADT)
* >> Datatype algebra
* >> Type constructors & Kinds
* Haskell
* Haskell Basics
* >> Elementary Haskell
* >> Intermediate Haskell
* >> Monads
* Advanced Haskell
* >> Fun with Types
* >> Wider Theory
* >> Haskell Performance
* Libraries Reference
* >> General Practices
* >> Specialised Tasks