The only required type annotated happens at the top-level module function and method level. The type-checker can infer most of the types at the local level.
Here is a simple example to show you the power of the type-inference algorithm:
The type checker can correctly deduce the type of lambda
(a, b, c) -> if a(b + 1) then b else c
((int) -> bool, int, int) -> int.
The type-checker first decides that
b must be
+ adds up two
ints. Then it knows
c must also be
c must have the same type. From the syntax,
be a function. Since the function application of
a happens at the boolean expression part of
we know it must return
a accepts one argument that is
int, the type of
a must be
(int) -> bool.
Although the type-checker is smart, in some cases it simply cannot determine the type because there is not enough information.
The type of
randomFunction() cannot be decided. We decide not to make it generic because we want
every expression to have a concrete type. In this case, the type checker will instantiate the