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

  • Let’s try to use 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!