Ad-hoc polymorphism
Ad-hoc polymorphism is better-known as overloading. This form of polymorphism allows multiple functions with the same name, but taking different types, to be defined; the compiler or interpreter automatically calls the right one. This way, functions appending lists of integers, lists of strings, lists of real numbers, and so on could be written, and all be called append, and the right append function would be called based on the type of lists being appended. This differs from parametric polymorphism, in which only one generic function needs to be written. Some argue that ad-hoc polymorphism is not polymorphism in a meaningful computer science sense at all, and is just a shorthand for the programmer calling append_integer and so on manually. This sort of polymorphism is most common in object-oriented programming languages, many of which also allow operators to be overloaded in a similar manner (see operator overloading).
Subtyping polymorphism
Some languages employ the idea of a subtype to state what objects are permitted. Subtyping polymorphism allows a function to be written so that it takes a certain type of object, but will work correctly if passed an object that is a subtype of the object it expects. For example, if in a certain programming language with subtyping polymorphism there were a type "Number", of which "Integer" and "Real Number" were subtypes, a function could be written so that it takes a Number, and works equally well whether an Integer or Real Number is passed. In object-oriented programming this is implemented with subclassing (inheritance), and is also known as late binding. See also Polymorphism in object-oriented programming.