Penguin

ProgrammingLanguages with PolymorphicTypes allow you to write great range of generic functions, yet preserve StrongTypeChecking?. With polymorphic typing you don't have to specify the exact type of everything in your program, you may use blank type variables.

This function type in OCaml is not polymorphic
val zip_ints : int list -> int list -> (int * int) list
That says zip_ints will take two lists of integers and return a list of pairs of integers. It's useful, but only for one thing. This function in OCaml is polymorphic
val zip : 'a list -> 'b list -> ('a * 'b) list
This zip takes two lists of items of types 'a and 'b (which may or may not be the same type) and returns a list of 'a and 'b pairs. When the compiler sees this function call
zip [1; 2; 3? ["orange"; "apple"; "banana"?

It will know that the result should be a list of integer/string pairs and type check the rest of the program accordingly.

ML and Haskell have polymorphic typing.

In C you can approximate polymophic typing with void pointer arguments, which will take pointers to any type. In Java and C++ approximate polymorphic typing by using Object classes, which all objects belong to. But in both cases you lose strong type checking, so the quality of your code suffers.

It should be noted here that this page is talking about what is sometimes known as parametric polymorphism. C++ has templates, which satisfy the definition above, but are known to be syntactic; each instantiation creates a specialised version of the code. In a "true polymorphic system" only one version of the generated code would be used. There are other ways to have polymorphic types, they often come up in ObjectOrientation. Oh, and parametric polymorphism is also often referred to as generics. -- SamJansen

Beginning with version 1.5 of the Java SDK, Java now also supports the concept of generics. -- DavidHallett

Java Syntax

Paramaterized Type

Vector<String> stringVector = new Vector<String> List<Integer> integerList = new List<Integer>

Interface

interface List<Element> implements !MyInterface?{...}

Class

class !MyList?<Element> {...} class !MyList?<Element> implements List<Element> {...}

Method

boolean containsBoth(Element a, Element b); static <Element> boolean swap(List<Element> list, int i, int j);

Java Generics on developer.java.sun.com

An Example

This is Glyn defining a binary tree type on his OCaml interpreter
  1. type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree ;;

type 'a tree = Leaf of 'a | Node of 'a tree * 'a tree

(That's Glyn typing at the OCaml interpreter prompt and OCaml responding.) The type tree is polymorphic: 'a is a place holder for any type. For example you might want a string tree
  1. let my_tree = Node (Node (Leaf "Cow", Leaf "Pig"), Leaf "Cat") ;;

val my_tree : string tree = Node (Node (Leaf "Cow", Leaf "Pig"), Leaf "Cat")

The OCaml interpreter worked that was a string tree for itself. From his tree type he can make int trees, char trees, string tree trees, whatever. These would all be incompatible types, because ints, chars and strings are incompatible. However, functions he writes for 'a trees can be used on any type of tree
  1. let rec count_leaves (t : 'a tree) : int = match t with | Leaf _ -> 1 | Node (left,right) -> count_leaves left + count_leaves right ;;

val count_leaves : 'a tree -> int = <fun>

  1. count_leaves my_tree ;;

- : int = 3

  1. count_leaves (Node (Leaf 1, Leaf 2)) ;;

- : int = 2