# Type Inference by Example, Part 2

Continuing where we left off in part 1, let’s look at a more advanced example that uses local variables and type constructors:

`function range(from, to) {`

let numbers = [];

for(let i = from; i <= to; i++) {

numbers[i - from] = i;

}

return numbers;

}

As in the previous installment, we add in fresh type variables:

`function range(from : $1, to : $2) : $3 {`

let numbers : $4 = [];

for(let i : $5 = from; i <= to; i++) {

numbers[i - from] = i;

}

return numbers;

}

Now, on the very first line, we encounter the empty array:

`let numbers : $4 = [];`

We know that it should be an Array<… something …>, but what is something? Why, a fresh type variable of course! So for this line, we get the following constraint:

`$4 == Array<$6>`

The next line starts the for loop:

`for(let i : $5 = from; i <= to; i++) {`

Wow, three statements in one line! Assuming that `++ : Int => Int`

, this gives us three constraints:

`$5 == $1`

$5 == $2

$5 == Int

The for loop body assigns a value to an index in `numbers`

:

`numbers[i - from] = i;`

This tells us two things: Numbers must be an array, and its element type must be the same as the type of `i`

.

`$4 == Array<$5>`

From the same line, assuming `— : (Int, Int) => Int`

we also constrain the types of `i`

and `from`

to be integers:

`$5 == Int`

$1 == Int

And finally, from the return statement, we constrain the return type to be the same as the type of `number`

:

`$3 == $4`

Now that we have generated all the constraints, let’s consider them all together:

`$4 == Array<$6>`

$5 == $1

$5 == $2

$5 == Int

$4 == Array<$5>

$5 == Int

$1 == Int

$3 == $4

Again, unification finds a substitution that solve the above system of equations, but let’s first consider the two constraints involving `Array`

. Because `$4`

is on the other side of both equations, we can simplify that to `Array<$6> == Array<$5>`

. Since both use a type constructor named `Array`

, we check the generic arguments against each other by generating the constraint `$6 == $5`

. And we already have another constraint that `$5 == Int`

. The resulting substitution is thus:

`$1 := Int`

$2 := Int

$3 := Array<Int>

$4 := Array<Int>

$5 := Int

$6 := Int

Applying that to our syntax tree, we get:

`function range(from : Int, to : Int) : Array<Int> {`

let numbers : Array<Int> = [];

for(let i : Int = from; i <= to; i++) {

numbers[i - from] = i;

}

return numbers;

}

And we’re done.

Stay tuned for part 3, where we’re going to look generic function calls.