Type-checking (checking the types of values in a program before it is run) can reject a program before it runs to prevent type errors from emerging.
Implicit typing
In implicitly-typed languages, the programmer rarely needs to specify the type of a binding.
Instead, the compiler will infer the type of a binding at compile time.
The following code snippet depicts such an inference.
fun f x = (* infer val f: int -> int *)
if x > 3
then 42
else x * 2
However, if the compiler is unable to infer a type, it will throw an error. (If the compiler can’t infer a type, it’s not its fault — you probably made a mistake somewhere in your code)
In the example below, the compiler won’t be able to infer a return type for the function g
as it returns a bool
in some situations and an int
in others
fun g x = (* report type error *)
if x > 3
then true
else x * 2
What is type inference?
g
earlier), it’s type inference’s job to fail and throw an error.There are 3 types of type inference
The greater the difficulty of type inference, the stricter the type inferencer is with deciding on types.
Determine type of bindings in order
For every val
or fun
binding,
x > 0
appears in code, x
will be constrained to the type int
since >
only operates on 2 values of type int
.x/3.0
appears in code, x
will be constrained to the type real
since /
only operates on 2 values of type real
.For any types that remain unconstrained (i.e. polymorphic), assign type variables (e.g. 'a
, 'b
).
Lastly, enforce the value restriction.