Lecture 05 Type Classes
Joseph Haugh
University of New Mexico
Polymorphism
- What is polymorphism?
- Polymorphism translates as “of many forms”
- Therefore, a polymorphic function is a function which can take on many forms or many types
Examples of Polymorphism
- What polymorphic functions have we already seen?
ghci> :t head
[a] -> a
ghci> :t tail
[a] -> [a]
ghci> :t length
[a] -> Int
Examples of Polymorphism
- head takes a list and returns the first element
- tail takes a list and returns everything but the first element
- length takes a list and calculates how many elements are in it
- Notice that none of the descriptions describe the elements
- This trait makes them able to be parametrically polymorphic!
Parametric Polymorphism
- A parametrically polymorphic function behaves the same no matter the type of its input (obviously it must type check)
- Let’s test to see if the above function indeed follow this rule
ghci> length [1,2,3]
3
ghci> length "abc"
3
ghci> length ["abc", "def", "ghi"]
3
Limits of Parametric Polymorphism
- When you can write your function this way do it!
- However, many function need to know a bit more about their arguments
- Do we have to then give up on polymorphism??
- Well let’s start by trying to write a function which takes an element and a list of those elements and returns if the element exists in the list
- This function is called
elem
in Haskell
- Lets try to write it!
elem Function
elem :: a -> [a] -> Bool
- Can we implement this function with this type?
- Let’s try it!
elem :: a -> [a] -> Bool
elem x [] = False -- We can do this!
elem x (y:ys) =
if x == y -- We can’t do this! Why?
then True
else elem x ys
elem Functions
Hmm well we could give up on polymorphism entirely
What would that look like?
elemInt :: Int -> [Int] -> Bool
elemInt = ...
elemFloat :: Float -> [Float] -> Bool
elemFloat = ...
elemChar :: Char -> [Char] -> Bool
elemChar = ...
You can see that this quickly becomes unmaintainable
So what are we to do?
Typeclasses
- Recall that the definition of a type is a collection of related values
- Well a typeclass is collection of related types
- They are related in the sense that they all implement a shared set of operations
- This should remind you of interfaces in Java
- How does this help us solve the
elem
problem?
- Well we need the values to all have equality defined, there’s a typeclass for that!
Eq
Revisiting elem
elem :: Eq a => a -> [a] -> Bool
elem x [] = False -- We can do this!
elem x (y:ys) =
if x == y -- We can do this too!
then True
else elem x ys
Eq Typeclass
The Eq typeclass defines the following 2 functions:
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
Thus, when we constrain our argument to be any type which is a member of Eq, we then gain these two function to use on that argument
Using Eq
ghci> 1 == 1
True
ghci> 1 /= 2
True
ghci> [1,2,3] == [3,2,1]
False
ghci> "abc" == "abc"
True
ghci> (1, 2.3) == (1, 2.3)
True
Ord Typeclass
- Ord is used for types which have an ordering
- Ord defines the following functions:
(<) :: a -> a -> Bool
(<=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(>=) :: a -> a -> Bool
min :: a -> a -> a
max :: a -> a -> a
Show Typeclass
- Show is used for turning values into a String
- Show defines the following function:
show :: a -> String
Read Typeclass
- Read is used for turing Strings into types
- Read defines the following function:
read :: String -> a
Num Typeclass
- Num is used types which can be treated as numerical
- Num defines the following functions:
(+) :: a -> a -> a
(-) :: a -> a -> a
(*) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
ghci’s :i
- That is a lot of information!
- What if you forget some of this?
- Use “:info” or “:i” in ghci to request information about something
- This includes typeclasses!
- Let’s try it!