Operator/function overloading refers to using the same function name for multiple function definitions, where the type signature of each definition involves a different return type, different types of parameters, and/or a different number of parameters. When an overloaded function is invoked, the applicable function definition to bind to the function call (obtained from a collection of definitions with the same name) is determined based on the number and/or the types of arguments used in the invocation. Function/operator overloading is also called ad hoc polymorphism. In general, operators/functions cannot be overloaded in ML and Haskell because every operator/function must have only one type:
Even in C, functions cannot be overloaded:
Thus, ML, Haskell, and C do not support function overloading; C++ and Java do support function overloading:
The extraction (i.e., input, ») and insertion (i.e., output, «) operators are commonly overloaded in C++ to make I/O of user-defined objects convenient:
Since ML does not support operators/function overloading,8 we cannot define a square function in ML that accepts any numeric value (e.g., integer or floating point):
The data type int is the default numeric type in ML (Section 7.9). However, we can define a square function in Haskell that accepts any numeric value:
The Haskell type class system supports the definition of what seem to be overloaded functions like square.9 Recall that the type class system allows values of different types to be used interchangeably if those types are properly related in the hierarchy. The flexibility fostered by a type or class hierarchy in the definition of functions is similar to ad hoc polymorphism (i.e., overloading), but is called interface polymorphism.
While they take advantage of the various concepts that render a static type system more flexible, ML and Haskell come with irremovable type checks for safety that generate error messages for discovered type errors and type mismatches.10 Put simply, ML and Haskell programs are thoroughly type-checked before run-time. Almost no ML or Haskell program that can run will ever have a type error. As a result, an ML or Haskell program that passes all of the requisite type checks almost never fails.
8. Some of the commonly used (arithmetic) primitive operators in ML are overloaded (e.g., binary addition).
3.17.181.61