We use cookies to give you a better experience, if that’s ok you can close this message and carry on browsing. For more info read our cookies policy.
6.3

# Type Classes in more Detail

## Type class and instance declarations

### Defining type classes

• A type class is a set of types for which some operations are defined.

• Haskell has some standard type classes that are defined in the Standard Prelude.

• You can also define your own.

### A type for bright colors

Suppose we’re computing with colors. Here’s a type, and a couple of functions.

    data Bright
= Blue
| Red

darkBright :: Bright -> Bool
darkBright Blue = True
darkBright Red  = False

lightenBright :: Bright -> Bright
lightenBright Blue = Red
lightenBright Red = Red


### A type for milder colors

Now, suppose we have a different type that needs similar functions.


data Pastel
= Turquoise
| Tan

darkPastel :: Pastel -> Bool
darkPastel Turquoise = True
darkPastel Tan       = False

lightenPastel :: Pastel -> Pastel
lightenPastel Turquoise = Tan
lightenPastel Tan       = Tan


### Defining a type class

• Both of our color types have functions to decide whether it’s dark, or to lighten it.

• We can define a class $Color$ and its corresponding functions.


class Color a where
dark :: a -> Bool
lighten :: a -> a


This says

• $Color$ is a type class

• The type variable $a$ stands for a particular type that is in the class $Color$

• For any type $a$ in $Color$, there are two functions you can use: $dark$ and $lighten$, with the specified types.

### Defining instances for the type class

• An $instance$ declaration says that a type is a member of a type class.

• When you declare an instance, you need to define the class functions.

• The following says that the type $Bright$ is in the class $Color$, and for that instance, the $dark$ function is actually $darkBright$.


instance Color Bright where
dark = darkBright
lighten = lightenBright

• Similarly, we can declare that $Pastel$ is in $Color$, but it has different functions to implement the class operations.

instance Color Pastel where
dark = darkPastel
lighten = lightenPastel


## Predefined type classes

Haskell provides several standard type classes. We have a look at two of them: $Num$ and $Show$.

### The Num class

• $Num$ is the class of numeric types.
• Here is (part of) its class declaration:
    class Num a where
(+), (-), (*) :: a -> a -> a


#### Num instances

• There are many numeric types; two of them are $Int$ and $Double$.

• There are primitive monomorphic functions that perform arithmetic on these types (these aren’t the real names):

addInt, subInt, mulInt :: Int -> Int -> Int
addDbl, subDbl, mulDbl :: Double -> Double -> Double

instance Num Int where
(-) = subInt
(*) = mulInt

instance Num Double where
(-) = subDbl
(*) = mulDbl


#### Hierarchy of numeric classes

• There are some operations (addition) that are valid for all numeric types.

• There are some others (e.g. trigonometric functions) that are valid only for some numeric types.

• Therefore there is a rich hierarchy of subclasses, including

• $Integral$ — class of numeric types that represent integer values, including $Int$, $Integer$, and more.

• $Fractional$ — class of types that can represent fractions.

• $Floating$ — class containing $Float$, $Double$, etc.

• $Bounded$ — class of numeric types that have a minimal and maximal element.

• $Bits$ — class of types where you can access the representation as a sequence of bits, useful for systems programming and digital circuit design.

• If you want to get deeply into numeric classes and types, refer to the Haskell documentation.

### The Show class

• We have been using $show$ to convert a data value to a string, which can then be written to output.

• Some values can be “shown”, but not all.

• For example, it is impossible in general to show a function.

• Therefore $show$ needs a type class!

#### Defining your own Show instance


data Foo = Bar | Baz


We might want our own peculiar string representation:


instance Show Foo where
show Bar = "it is a bar"
show Baz = "this is a baz"


Recall that when you enter an expression $exp$ into ghci, it prints $show exp$. So we can try out our strange instance declaration:


*Main> Bar
it is a bar
*Main> Baz
this is a baz


#### Deriving Show

This is a similar type, but it has a $deriving$ clause.


data Foo2 = Bar2 | Baz2


Haskell will automatically define an instance of $show$ for $Foo2$, using the obvious definition:


*Main> Bar2
Bar2
*Main> Baz2
Baz2


### More standard typeclasses

Here is a summary of some of the type classes defined in the standard libraries.

• $Num$ — numbers, with many subclasses for specific kinds of number.

• $Read$ — types that can be “read in from” a string.

• $Show$ — types that can be “shown to” a string.

• $Eq$ — types for which the equality operator $==$ is defined.

• $Ord$ — types for which you can do comparisons like $% $, $>$, etc.

• $Enum$ — types where the values can be enumerated in sequence; this is used for example in the notation $[1..n]$ and $'a'..'z'$.


*Main> [1..10]
[1,2,3,4,5,6,7,8,9,10]
*Main> ['a'..'z']
"abcdefghijklmnopqrstuvwxyz"