3.4 polymorphic types

Note that we will have functions that want to act on many types, or types of a certain format. In this sense, we introduce type variables, which will be variables that refer to elements within the set Types. The standard example is:

map :: (a -> b) -> [a] -> [b] -- For all types a, b, map has this type.
reverse :: [a] -> [a] -- For all types a, reverse has type [a] -> [a].

We call these functions polymorphic, as there are many different possible types. Haskell is smart enough for restraining the type class if it needs some property that the function utilizes. You can also override functions for specific types, by defining the function of a different type. This is parametric polymorphism, since we're changing the behavior of a polymorphic function based on its parameters:

reverse :: [Char] -> [Char] -- Won't override reverse :: [Int] -> [Int]

This is nice, and let's us say things about certain types of functions in general (commutativity of map, etc.), but the theorems we get aren't super interesting because of this generality.