Type Propagation

[Ch. 1: Overview and History]
[Syntax]
[Names and Scope]
[Types and Type Systems]
[Semantics]
[Functions]
[Memory Management]
[Imperitive Programs and Functional Abstraction]
[Modular and Class Abstraction]
[Functional Programming]
[Logic Programming]

In an expression, each token (constant or variable) has some value. The language rules specify how to apply each operator to the values, and what the result is. If we evaluate:

double d = 3.7;

2.5*(x + y - 1) - d;

x + y | Add 10 and 21 to make 31. |

x + y - 1 | Subtract 1 from 31 to make 30. |

2.5*(x + y - 1) | Convert 30 to 30.0 and multiply to get 75.0. |

2.5*(y + 1) - d | Subtract 3.7 from 75.0 giving 71.3. |

Just as the language has rules to operate on values, so with types:

x + y | The sum of integers is an integer. |

x + y - 1 | The difference of integers is an integer. |

2*(x + y - 1) | The product of a float and an integer is a float. |

2*(y + 1) - d | The difference of floats is a float. |

While values must be computed at run time,
in a statically-typed language, types can be
determined at compile time. This simplifies computation of values at
run time, since the types are already known.
In a dynamically-typed language, the full translation of `x + y` might
look something like:

if `x` and `y` are integers, add them with an integer addition;

else if`x` and `y` are float, add them with a float addition;

else if`x` and `y` are strings, call the string concatenation function;

else if one of`x` and `y` is a float and the other an integer,

convert the integer to float and perform a float addition;

else raise a type error exception

If the language has more meanings for +, there will be more cases. But for a
statically-typed language, the translation of
else if

else if

else if one of

convert the integer to float and perform a float addition;

else raise a type error exception

This is also a reason why statically-typed languages usually have
homogeneous arrays.
If array `a` is heterogeneous, then the type of
`a[i]` can vary depending on the value of `i`, since
different array positions can have different types. Because the value of
`i` cannot (always) be known at compile time, the type
of `a[i]` cannot be known either.
But when `a` is homogeneous, the type of `a[i]` is constant.

A dynamically-typed language will have to check the type of
`a[i]` at run-time anyway, so it has nothing to gain by making
`a` homogeneous.