Version 6 (modified by john@…, 10 years ago) (diff) |
---|

# Scoped Type Variables

See ExtensionDescriptionHowto for information on how to write these extension descriptions. Please add any new extensions to the list of HaskellExtensions.

## Brief Explanation

Type annotations, which Haskell 98 allows in expressions, are also allowed in patterns and (currently in GHC only) in result type signatures, attached to the left side of a function definition. New type variables in these annotations scope over the function body, permitting locally defined variables to be given signatures in situations where it would be impossible in Haskell 98, e.g.

sortImage :: Ord b => (a -> b) -> [a] -> [a] sortImage (f::a->b) = sortBy cmp where cmp :: a -> a -> Ordering cmp x y = compare (f x) (f y)

## References

Note that although GHC and Hugs use the same syntax, the meaning of type variables is quite different, and there are other differences too.

## Pros

- Allows better documentation (without them, some expressions cannot be annotated with their types).
- Extensions such as RankNTypes and GADTs require such annotations, so even more important in conjunction with them.

## Cons

- Many different forms of scoped type variables in GHC makes them hard to reason about.
For example:
f :: a -> a f = \x -> (x :: a)

is rejected butg = let f :: a -> a = \x -> (x :: a) in f

is allowed.

- A rule like ExplicitQuantification would most likely be needed if these were put into the standard.

## Proposal 1

both pattern bound and let type signature bound variables are in scope in the body of a function. only let type signature bound variables may shadow other variables and no variables are ever in scope in a let type signature, pattern bound variables do not shadow but rather refer to the same type. ExplicitQuantification is required for all expression type signatures but not let type signatures.

This proposal tries to strike a balance between backwards compatability, avoiding accidental type errors, and simplicity. let type signatures always create a new scope, pattern bound ones are always in the same scope and it is clear from expression type signatures what is a scoped type var.