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
deriving (Read, Show)
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
deriving (Read, Show)
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
(+) = addInt
(-) = subInt
(*) = mulInt
instance Num Double where
(+) = addDbl
(-) = 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!
- [show :: Show, a Rightarrow a rightarrow ,String]
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
deriving (Read, Show)
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"
Functional Programming in Haskell: Supercharge Your Coding
Functional Programming in Haskell: Supercharge Your Coding
Register to receive updates
-
Create an account to receive our newsletter, course recommendations and promotions.
Register for free







