These lecture notes are based on chapter 7 in ``Programming Language Concepts and Paradigms'' by David Watt and the Java Language Tutorial from Sun.
Are type declarations really needed? Remember the factorial function. Let's write the factorial function in Pascal, but without typing variables and try to figure out what type it returns.
{ factorial function }
function factorial ( x : ? ) : ?;
begin
if x = 0 then factorial := 1;
else factorial := x * factorial(x - 1);
end;
We can infer that factorial returns an integer value because it
returns a 1, and we can infer that x is an integer because we
compare it to an integer.
We could then check all the calls to factorial to determine if they
passed an integer.
But it is not always possible to infer monomorphic types.
{ identity function }
function identity ( input : ? ) : ?;
begin
identity := input;
end;
What type of value is returned? A polymorphic type (i.e., any type).
Type inference is typically done to improve the efficiency of ``typeless'' languages. For example, the Icon compiler does type inference.
# Icon example
letter := 'c'; # we know that letter is a char
letter2 := letter; # can generate code to do a byte move since a char
# is byte sized.
Often it is convenient for a programmer to mix different types in an expression (often an arithmetic expression). Most languages recognise and implicitly coerce values to the appropriate types when it makes sense.
int x;
double y;
char ch;
x = 20;
y = (x * 4); /* result of x * 4 is coerced to a float */
/* it makes sense to convert an int to a float */
ch = y; /* not coerced, error */
Coercion is often from narrower to wider types (widening), for instance from
integers to reals (can think of integers as a subset of reals).
But we could coerce from reals to integers (truncation).
In some languages, we can explicitly coerce between types that are not normally coerced via casts.
double y; char ch; y = 1.0; ch = (char) y; /* what ends up in ch? */