Coders everywhere are familiar with simple types: those are like printing presses that produce new instances when their new() button (or whatever) is pressed. With this metaphor, parametric polymorphism means an ability to create printing presses that produce other printing presses. Parametrizable (generic) types are types that are not completely specified, and thus need to be fully ground before being used. An example (based on the syntax of Pizza/GJ, an extension to Java):

public class CloneableNumberList<T extends Number, implements Cloneable>
{
public CloneableNumberList() {
... implementation omitted for brevity ...}
public CloneableNumberList(Iterator<T> iter) {
... implementation omitted for brevity ...}
public T get(int index) {
... implementation omitted for brevity ...}
public void add(T element) {
... implementation omitted for brevity ...}
}

Usage:

CloneableNumberList<Double> cnl = new CloneableNumberList<Double>();
cnl.add(new Double(1.2));
cnl.add(new Double(3.4));
cnl.add(new Boolean(false));    // compile-time (not run-time) error
System.out.println(cnl.get(2).toString());

Generic types are fairly well-spread in the programming language world. SML has the cleanest such system, leaving the sorry excuse that is the C++'s template mechanism (a glorified #define that bloats code) in the dust.