Scoped type variables
Simon Peyton-Jones
simonpj@microsoft.com
Tue, 8 May 2001 00:47:58 -0700
Hi Mark,=20
Thanks for your reply.
| | Arguments in favour:
| | - It's more like term-variable pattern matching
|=20
| Term variables in a pattern are binding occurrences, but type=20
| variables are not. Making the latter look more like the=20
| former would appear to be a recipe for unnecessary confusion=20
| given that that they are actually different.
Why do you say "type variables are not"?. When I say
f x =3D e
I mean "inside e, use x as the name for whatever value is=20
passed as argument to f".
Under what Marcin proposes=20
f (x::a) =3D e
would mean "inside (type signatures in) e, use a as the name for
whatever type is the type of the argument passed to f".
When you say there's a good theoretical foundation (typed lambda
calcului) I think you are imagining that when we say
f (x::a) =3D e
we are saying "There's a /\a as well as a \x::a in this definition". In
which
case it would certainly be wrong to allow
f :: Int -> Int
f (x::a) =3D e
But I'm suggesting something different
* Place the big lambdas wherever they would be now (i.e. not influenced
by the position of (x::a) type signatures.
* Explain the pattern type signatures as let-bindings for types. Thus
we might translate f to system-F like this:
f =3D \x::T -> let-type a =3D T in e
I've use let-type here, but one could equally well say (/\a -> e) T.
This (admittedly informal) translation works fine if T happens to be
Int,
for exampe; i.e. x's type is not universally quantified. =20
In short, the pattern type signature is used solely to bind names to
types,
and not for universal quantification. I want to have a slightly more
elaborate
let-type, thus:
g :: (Int,Bool) -> Int
g (x::(a,b)) =3D e
translates to
g =3D \x::(Int,Bool) -> let-type (a,b) =3D (Int,Bool) in e
But notice that the RHS of a pattern-matching let-type is statically
guaranteed to have the right shape. So I don't allow
let-type (a,b) =3D c in ...
(where c is a type variable). So it's just syntactic sugar, like
let-type itself,
and I could equally well write
g =3D \x::(Int,Bool) -> let-type a =3D Int; b =3D Bool in e
OK, so there are two questions
a) does that answer the question about the techincal foundation
b) is it a good design from a software engineering point of view
I hope the answer to (a) is yes, but I realise that opinions may differ
about (b).
I thought this might be of general enough interest to be worth
continuing to cc the
Haskell list.
Simon