Lexically Scoped Annotations in Chameleon

In Chameleon the scope of type variables introduced in a type annotation is the entire body of that declaration. Thus, we assume that all variables occuring in a type annotation are implicitely quantified unless the variable has been introduced by an annotation in the outer scope.

Consider the program.

prefix :: b->[[b]]->[[b]]
prefix x yss = let xcons :: c -> [b]->[b]
                   xcons v ys = x:ys
               in map (xcons undefined) yss
Quantifiers are left implicit. Note that function prefix has type forall b.b->[[b]]->[[b]] whereas xcons has type forall c.c->[b]->[b]. Lexically scoped annotations in Chameleon differ to the ones found in GHC. The proposal by Peyton-Jones and Shields makes it necessary to introduce scoped type variables explicitely in pattern bindings. Here is the Haskell version of the previous example.
prefix :: a->[[a]]->[[a]]
prefix (x::b) yss = let xcons :: c -> [b]->[b]
			xcons v ys = x:ys
		    in map (xcons undefined) yss
In our opinion, scoped variables introduced in pattern bindings are redundant. In particular, this becomes apparant in case we switch to an explicitly typed System F style translation where universal quantifiers are represented by typed lambdas. The above example can be translated as follows.
prefix /\ b. \ x::b -> \yss:b ->  
  let xcons = /\ c. \v::c -> ys::b -> x:ys
  in ....
Currently, the proposal by Peyton-Jones and Shields does not allow references to scoped constraints appearing only in the type component which is naturally supported in our approach. Consider the program:
-- introduce eval as an overloaded identifier
overload eval
f :: (Eval (a->(b,c))) => a->b 
f x = fst ((eval x) :: (b,c))
The lexically scoped variable c refers to the ``global'' constraint Eval (a->(b,c)). Note that we automatically connect lambda-bound variables to type annotations. For example, variable x has type a. Hence, we avoid the need for pattern bindings. Here is the previous example with pattern bindings.
f :: (Eval (a->(b,c))) => a->b 
f (x::a) = fst ((eval x) :: (b,c))
Note that in Chameleon we do not support pattern bindings because such bindings can be derived from the annotation.

In Chameleon, we also support a form of ``existential'' type annotation. Consider the following program.

f ::: a->a
f True = False
The annotation f ::: a->a states that f has type a->a for some a. We can arbitrarily mix both forms of annotations. Consider
f ::: a->a
f x = let g :: a->a
          g y = undefined
      in g x
Consider the following program. Our intention is to enforce that x and y are of the same type.
f x y = (x:::a, y:::a)
However, the two occurences of variable a refer to different scopes. The following code does the job.
f x y = let z ::: a->c
            z _ = (x:::a, y:::a)
        in z undefined
Note that this trick can be used to introduce a ``shared'' scoped type variable.

Chameleon programs are translated to plain Haskell (i.e. Chameleon overloaded identifiers are resolved, that's it). Currently, we employ the following strategy.

This is a comprise. There are cases where a program crucially relies on its type annotations (e.g. see polymorphic recursion). For more details we refer to the TR.