...and the biggest reason is the presence of polymorphic static types with type inference.
"Polymorphic" simply means that there are functions and values
which can have multiple types. Or, put differently, there are
types which can "stand for" multiple other types. For example,
the value nil
:
- nil; val it = [] : 'a list
is polymorphic because the 'a
parameter can stand
for any type. Therefore this value can have multiple types: int
list, string list, etc. Assigning specific types to type
variables of a polymorphic type is called instantiating the
type.
Trivia Bit 1: There are many kinds of polymorphism; the form ML uses is called "universal" or "Hindley-Milner" polymorphism. Trivia Bit 2: Yes, there are "monomorphic" type systems. Pascal is a good example.
At a very high level, here is the general algorithm for determining types:
fun myIf(x, y, z) = if x then y else z; fun squid(a, b, c) = let val d = [2.0,3.0]; val e:(int * (int * string)) = (3, c); in if a > hd(d) then [hd(b), #2(c)] else tl(b) end;