Polymorphic types
We study the concept of polymorphic types in Haskell and write polymorphic versions of previously written functions.
Introduction to polymorphism
So far, all the functions we have written ourselves operated on concrete types. For example, the containsMatchingInt
function from the previous lesson operates on functions of type Int -> Bool
and lists of type [Int]
. It can not process functions or lists of any other type.
containsMatchingInt :: (Int -> Bool) -> [Int] -> Bool
containsMatchingInt test [] = False
containsMatchingInt test (x:xs) | test x == True = True
| otherwise = containsMatchingInt test xs
The concept of containsMatching
, however, is more general. We could write a similar function for lists of doubles, where the predicate also changes to a test on doubles.
containsMatchingDouble :: (Double -> Bool) -> [Double] -> Bool
containsMatchingDouble test [] = False
containsMatchingDouble test (x:xs) | test x == True = True
| otherwise = containsMatchingDouble test xs
Similarly, one might write containsMatchingChar
, containsMatchingString
, and so on. But all of these functions use the same general concept of containsMatching
. Instead of writing the same logic for each concrete type, we should strive to implement a general containsMatching
function that can work on lists of any type.
We know functions that behave like this from the Haskell Prelude. Some examples are the head
and tail
functions that work on lists of arbitrary element types. These functions are polymorphic, which means that they can be applied not only to arguments of just one concrete type, but to a whole range of argument types. In this case, lists of any kind. Let’s see how we can write polymorphic functions ourselves.
Writing polymorphic functions on lists
When we compare the implementation of containsMatchingInt
with containsMatchingDouble
, we can see that except for the function name, the equations are the same. The only difference is the type declaration. In fact, the only thing we need to change to make the function polymorphic is to make the type declaration more general. Here is our polymorphic ...