ichudov@wiltel.com (Igor Chudov) writes:
|> 1. They are just different and not even very similar.

and in the same vein, in article 94-10-180,
ryer@dsd.camb.inmet.com (Mike Ryer) writes:

|> Overloading happens at compilation time -- the compiler decides which function
|> to invoke based on statically-determined types of the operands.

|> Polymorphism may not happen until runtime -- the compiler generates code that
|> fans out based on the runtime value of a tag.

I don't think so. At least, if the two folks quoted above aren't completely
off base, then the terms are being used differently in the OO and functional
communities. Most recent functional programming languages have static
polymorphic type systems.

It was Strachey who coined the terms "parametric polymorphism" and "ad-hoc
polymorphism". The former refers to a type with a universally-quantified
type parameter. (Any type can be substituted for the type variable.)
For example (using Haskell notation),

length :: [a] -> Int
map :: (a -> b) -> [a] -> [b]

Here, a and b are type variables, a -> b denotes a function from a to b,
and [a] is "list of a". A function with a parametric type, in a sense
that can be made precise, has the same semantics at every monomorphic
instance. It can be implemented with the same code for all such instances
(though nothing prevents a compiler from generating some specialized
versions, depending, for example, on the size of objects of the parametric
type). The code "knows" nothing about the parametric type. In C++,
templates give you a kind of parametric polymorphism.

Ad hoc-polymorphism refers to using the same name for functions with
different (or potentially different) semantics. Implementationally, this
means different code for different instances. "Overloading" is the most
free-wheeling form of ad-hoc polymorphism, involving nothing more than the
reuse of a name, perhaps not even requiring different referents of an
overloaded function name to have the same arity. Method specialization in
OO languages and type classes in Haskell represent a more restrained form
of ad-hoc polymorphism (still called "overloading" in Haskell, though), in
which all monomorphic instances have the same "shape". In Haskell, we say
that we still have universally quantified type parameters, but over
specific _type_classes_, not over the universe of types. For example,

(+) :: (Num a) => a -> a -> a

means that + takes two arguments of the same numeric type (an instance of
the type class Num) and returns a value of that same type.
(+) :: (Int -> Int -> Int) and (+) :: (Float -> Float -> Float) are
two monomorphic instances (with differing semantics).

Now, all of this is a separate question from whether types are static
or dynamic. The type parameter of an instance of a parametric type might be
known statically (in which case the compiler might choose to generate
specialized code) or not. The determination of which instance an overloaded
name refers to might be static (as with arithmetic operators in Fortran, C,
Pascal, ...) or dynamic (for example, Smalltalk).