Type classes
| What a class is | |
| deriving | |
| Reading a constraint | |
| Write an instance |
What a class is
A type class is a set of functions that several types can implement. It is closer to an interface than to an object-oriented class: the type stays plain data, and behaviour is added from outside.
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
instance Eq Bool where
True == True = True
False == False = True
_ == _ = False
The four classes you meet first are Eq for equality, Ord for ordering, Show for printing, and Num for arithmetic.
deriving
For your own data types the compiler writes the boring instances. Ask for the ones you need and move on:
data Color = Red | Green | Blue
deriving (Eq, Ord, Show)
-- Red == Red True
-- show Green "Green"
-- Red < Blue True, by declaration order
The derived Ord follows the order of the constructors, which is rarely what a domain wants. Define compare by hand when the order is meaningful.
Reading a constraint
The part before the fat arrow restricts which types fit. It is a promise the caller must keep, not a conversion:
maximumOf :: Ord a => [a] -> a
maximumOf = foldr1 max
maximumOf [3,1,2] -- 3
-- maximumOf [True,False] works too
Read it as: for any type a that can be ordered, this takes a list of a and returns one a. Nothing about the body depends on knowing which type it is.
Write an instance
An instance for your own class needs the class first. A small one for describing values is a good exercise:
class Describe a where
describe :: a -> String
instance Describe Color where
describe Red = "the color of blood"
describe Green = "the color of grass"
describe Blue = "the color of sky"
Every instance must cover every method without a default. That is
the same exhaustiveness rule as a pattern match, applied one level
up.
Next:
Parametric polymorphism
Article author: Arthur Isaev