I would like to understand the key difference between parametric polymorphism such as polymorphism of generic classes/functions in the Java/Scala/C++ languages and \"ad-hoc\
Parametric polymorphism means, we don't care about the type, we'll implement the function the same for any type. For example, in Haskell:
length :: [a] -> Int
length [] = 0
length (x:xs) = 1 + length xs
We don't care what the type of the elements of the list are, we just care how many there are.
Ad-hoc polymorphism (aka method overloading), however, means that we'll use a different implementation depending on the type of the parameter.
Here's an example in Haskell. Let's say we want to define a function called makeBreakfast
.
If the input parameter is Eggs
, I want makeBreakfast
to return a message on how to make eggs.
If the input parameter is Pancakes
, I want makeBreakfast
to return a message on how to make pancakes.
We'll create a typeclass called BreakfastFood
that implements the makeBreakfast
function. The implementation of makeBreakfast
will be different depending on the type of the input to makeBreakfast
.
class BreakfastFood food where
makeBreakfast :: food -> String
instance BreakfastFood Eggs where
makeBreakfast = "First crack 'em, then fry 'em"
instance BreakfastFood Toast where
makeBreakfast = "Put bread in the toaster until brown"
According to John Mitchell's Concepts in Programming Languages,
The key difference between parametric polymorphism and overloading (aka ad-hoc polymorphism) is that parameteric polymorphic functions use one algorithm to operate on arguments of many different types, whereas overloaded functions may use a different algorithm for each type of argument.