[http://trac.haskell.org/ddc/wiki/Language/Overview < Overview]
= Closure Typing =
== Region sharing ==
Consider the following function:
{{{
f ()
= do x = 5
g () = x
g
}}}
Without closure information this function would have the following extended type:
{{{
f :: forall %r. () -> () -> Int %r
}}}
Remember that the `forall %r` at the front of the type is supposed to indicate that the return value is freshly allocated. This is certainly true if we apply both arguments:
{{{
twoSeparateInts :: Tuple2 %r1 (Int %r2, Int %r3)
twoSeparateInts = (f () (), f () ())
}}}
In the type of `twoSeparateInts`, the different regions variables on each of the `Int` constructors means that they do not alias. This in turn means that it is safe to treat one as `Const` and the other as `Mutable`.
But what happens if we partially apply `f`? The standard type system will re-generalize the type for the new binding and we're left with:
{{{
f_unit :: forall %r1. () -> Int %r1
f_unit = f ()
}}}
We've now got a function which returns the ''same'' `Int` every time we call it, but the type says it's supposed to be fresh! The problem here is that `x` was free in our original definition of `g` so is shared between applications of it.
== Closure typing for region sharing ==
Closure typing is used to track the sharing of regions between function calls.
The type inferred for `f` is actually:
{{{
f :: forall %r0
. () -> () -($c0)> Int %r0
:- $c0 = x : %r0
}}}
The `$c0` annotation tells us that this function has a object free in its closure, and that the object contains region `%r0`. The `x : %r0` syntax gives a name to this term, and is pronounced "x ''of'' region zero".
If we use this new type and apply the first argument we have:
{{{
f_unit :: () -($c0)> Int %r0
:- $c0 = x : %r0
}}}
This type says that `f_unit` is a function that takes a unit value and returns an `Int`, but the `Int` is free in its closure so is shared by all calls to it. The type system does not generalise regions which are free in these closures.