Type Inference

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 must be ((int) -> bool, int, int) -> int.

The type-checker first decides that b must be int since + adds up two ints. Then it knows that c must also be int, because b and c must have the same type. From the syntax, a must be a function. Since the function application of a happens at the boolean expression part of if, we know it must return bool. Since 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.

class NotEnoughTypeInfo {
function <T> randomFunction(): T = panic("I can be any type!")
function main(): unit = { val _ = randomFunction(); }
}

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 generic type T as unit.