Example: Ad Hoc Solution to Type Constraints

Let's rearrange the type constraints into a canonical order, duplicating all type constraints that contain a type variable on both sides of the equality.

    ta = t16
    ta = t29

    ti = t26

    tj = t24

    tm = t3
    tm = t12
    tm = (txt21)

    tx = t6
    tx = t9

    ty = t14
    ty = t18

    t1 = int
    t2 = int
    t3 = tm
    t3 = (t1t4)
    t4 = (t2t5)
    t5 = t22
    t6 = tx
    t6 = int
    t7 = bool
    t7 = bool
    t8 = int
    t8 = t20
    t9 = tx
    t9 = int
    t10 = int
    t10 = int
    t11 = int
    t12 = tm
    t12 = (t11t13)
    t13 = (t14t15)
    t14 = ty
    t16 = ta
    t16 = (t15t17)
    t17 = (t18t19)
    t18 = ty
    t19 = t20
    t20 = t19
    t20 = t8
    t21 = (tyt20)
    t22 = t5
    t22 = t30
    t23 = int
    t23 = int
    t24 = tj
    t24 = int
    t25 = int
    t25 = int
    t26 = ti
    t26 = int
    t27 = int
    t28 = (tjt27)
    t29 = (tit28)
    t30 = t22

A ground type is a type that contains no type variables. If one of our type constraints says that a type variable is equal to a ground type, then we know the value of that type variable. We might as well substitute its value for all occurrences. While we're at it, we will eliminate redundant type constraints.

    ta = t16
    ta = t29

    ti = int

    tj = int

    tm = t3
    tm = t12
    tm = (txt21)

    tx = int

    ty = t14
    ty = t18

    t1 = int
    t2 = int
    t3 = tm
    t3 = (int → t4)
    t4 = (int → t5)
    t5 = t22
    t6 = tx
    t6 = int
    t7 = bool
    t8 = int
    t8 = int
    t9 = tx
    t9 = int
    t10 = int
    t11 = int
    t12 = tm
    t12 = (int → t13)
    t13 = (t14t15)
    t14 = ty
    t16 = ta
    t16 = (t15t17)
    t17 = (t18t19)
    t18 = ty
    t19 = int
    t20 = t19
    t20 = int
    t21 = (ty → int)
    t22 = t5
    t22 = t30
    t23 = int
    t24 = tj
    t24 = int
    t25 = int
    t26 = ti
    t26 = int
    t27 = int
    t28 = (tj → int)
    t29 = (tit28)
    t30 = t22

Those substitutions created some more constraints that have a ground type on the right hand side, so we substitute again.

    ta = t16
    ta = t29

    ti = int

    tj = int

    tm = t3
    tm = t12
    tm = (txt21)

    tx = int

    ty = t14
    ty = t18

    t1 = int
    t2 = int
    t3 = tm
    t3 = (int → t4)
    t4 = (int → t5)
    t5 = t22
    t6 = int
    t7 = bool
    t8 = int
    t9 = int
    t10 = int
    t11 = int
    t12 = tm
    t12 = (int → t13)
    t13 = (t14t15)
    t14 = ty
    t16 = ta
    t16 = (t15t17)
    t17 = (t18 → int)
    t18 = ty
    t19 = int
    t20 = int
    t21 = (ty → int)
    t22 = t5
    t22 = t30
    t23 = int
    t24 = int
    t25 = int
    t26 = int
    t27 = int
    t28 = (int → int)
    t29 = (tit28)
    t30 = t22

And again:

    ta = t16
*   ta = (int → (int → int))

    ti = int

    tj = int

    tm = t3
    tm = t12
*   tm = (int → t21)

    tx = int

    ty = t14
    ty = t18

    t1 = int
    t2 = int
    t3 = tm
    t3 = (int → t4)
    t4 = (int → t5)
    t5 = t22
    t6 = int
    t7 = bool
    t8 = int
    t9 = int
    t10 = int
    t11 = int
    t12 = tm
    t12 = (int → t13)
    t13 = (t14t15)
    t14 = ty
*   t16 = (int → (int → int))
    t16 = (t15t17)
    t17 = (t18 → int)
    t18 = ty
    t19 = int
    t20 = int
    t21 = (ty → int)
    t22 = t5
    t22 = t30
    t23 = int
    t24 = int
    t25 = int
    t26 = int
    t27 = int
    t28 = (int → int)
*   t29 = (int → (int → int))
    t30 = t22

That was the easy part. Now things get interesting. Let's focus on these constraints:

    ta = t16
    ta = (int → (int → int))

    ti = int

    tj = int

    tm = t3
    tm = t12
    tm = (int → t21)

    tx = int

    ty = t14
    ty = t18

    t3 = (int → t4)
    t4 = (int → t5)
    t5 = t22
    t12 = tm
    t12 = (int → t13)
    t13 = (t14t15)
    t14 = ty
    t16 = (int → (int → int))
    t16 = (t15t17)
    t17 = (t18 → int)
    t18 = ty
    t21 = (ty → int)
    t22 = t5
    t22 = t30
    t28 = (int → int)
    t29 = (int → (int → int))
    t30 = t22

In particular:

    ty = t14
    ty = t18

    t16 = (int → (int → int))
    t16 = (t15t17)
    t17 = (t18 → int)
    t18 = ty

A matching process known as unification tells us that

    ty = t14
    ty = t18

*   t15 = int
    t16 = (int → (int → int))
    t16 = (t15t17)
    t17 = (t18 → int)
*   t18 = int
    t18 = ty

Adding these new constraints, and substituting equals for equals, we get

    ta = (int → (int → int))

    ti = int

    tj = int

    tm = t3
    tm = t12
    tm = (int → t21)

    tx = int

*   ty = int

    t3 = (int → t4)
    t4 = (int → t5)
    t5 = t22
    t12 = tm
    t12 = (int → t13)
*   t13 = (int → t15)
*   t14 = int
    t16 = (int → (int → int))
*   t16 = (t15 → (int → int))
*   t17 = (int → int)
    t18 = int
*   t21 = (int → int)
    t22 = t5
    t22 = t30
    t28 = (int → int)
    t29 = (int → (int → int))
    t30 = t22

In particular:

    tm = t3
    tm = t12
    tm = (int → t21)

    t3 = (int → t4)
    t4 = (int → t5)
    t5 = t22
    t12 = (int → t13)
    t13 = (int → t15)
*   t14 = int
    t16 = (int → (int → int))
*   t16 = (t15 → (int → int))
*   t17 = (int → int)
    t21 = (int → int)
    t22 = t5
    t22 = t30
    t30 = t22

Substitution and unification yield

    tm = t3
    tm = t12
*   tm = (int → (int → int))

*   t3 = (int → (int → int))
*   t4 = (int → int)
*   t5 = int
*   t12 = (int → (int → int))
*   t13 = (int → int)
    t14 = int
    t15 = int
    t16 = (int → (int → int))
*   t16 = (int → (int → int))
    t17 = (int → int)
    t21 = (int → int)
*   t22 = int
    t22 = t30
*   t30 = int

Hence we arrive at the following complete solution to the system of type constraints:

    ta = (int → (int → int))

    ti = int

    tj = int

    tm = (int → (int → int))

    tx = int

    ty = int

    t1 = int
    t2 = int
    t3 = (int → (int → int))
    t4 = (int → int)
    t5 = int
    t6 = int
    t7 = bool
    t8 = int
    t9 = int
    t10 = int
    t11 = int
    t12 = (int → (int → int))
    t13 = (int → int)
    t14 = int
    t15 = int
    t16 = (int → (int → int))
    t16 = (int → (int → int))
    t17 = (int → int)
    t18 = int
    t19 = int
    t20 = int
    t21 = (int → int)
    t22 = t5
    t22 = int
    t23 = int
    t24 = int
    t25 = int
    t26 = int
    t27 = int
    t28 = (int → int)
    t29 = (int → (int → int))
    t30 = int

The program is well-typed, and evaluates to an int.


Last updated 24 March 2008.

Valid XHTML 1.0!