
Hi all, (I'm writing this to several lists since it involves GHC (implementation of extensions), cabal (registration of extensions) and some future Haskell standard (formalisation of extensions).) In my quest to implement all known syntactic extensions to Haskell in my haskell-src-exts package, I've become painfully aware of the sometimes ad-hoc nature that these extensions have been added to GHC. This should not be taken as criticism per se, GHC is awesome and I'm sure a lot of thought and research has gone into all of these extensions. I think the problem (from my point of view) is rather that most of the extensions are only really "interesting" on a type system level, whereas the syntactic level is rather trivial, and thus the latter has (rightly) gotten far less formal attention. I hope my putting the light on these issues will be a help and a kickoff towards improving the state of formalisation of the known and registered (with Cabal) extensions. One of the most blatant and (to me) problematic such issues is the matter of using 'forall'. GHC has a number of extensions relating to the use of forall-quantified types in various interesting ways. With none of these extensions on, forall is not considered a keyword, so the syntax with explicit forall quantification cannot be used at all ('forall' is considered a varid). However, with *any* extension on that relates to forall-quantified types, forall is a keyword, and can syntactically be used in types *anywhere*. This doesn't mean all such types will pass the type checker, most of them won't in fact, but syntactically there is really no (or at least very little) difference. Conceptually, all of these extensions (specifically PolymorphicComponents, Rank2Types, RankNTypes, LiberalTypeSynonyms and ScopedTypeVariables (and strangely also ExistentialQuantification)) thus have one thing in common. They all enable syntactically forall-quantified types. They allow different uses of these types as far as the type system is concerned, but syntactically there is no difference between type and type (in fact there cannot be, as I discussed in a recent blog post [1]). Funnily enough there are also some uses of forall-quantified types that are common to all of these extensions - using a forall just to make polymorphism explicit in a type doesn't change anything as far as the type system is concerned, so e.g. the types '(Eq a) => a -> Bool' and 'forall a . (Eq a) => a -> Bool' are equivalent. The latter type can be given to a function when any of the listed six extensions are given, even if most of them have nothing to do with this at all! So, what I'm getting at is an idea that Isaac Dupree gave as a comment to my blog post. He said: "I wish there was a plain old ExplicitForall extension that enabled the keyword in types (without extending the type checker -- only like (id :: forall a. a -> a) would be allowed)". I think this is a really great idea. I find it conceptually appealing, since I think it covers exactly that blind spot that is the seemingly unintended intersection between all these extensions. And it also makes the separation of concern between the syntactic level and the type system more clear. Any formalisation of any of the type system extensions would not need to bother with syntactic details, but can simply be said to imply ExplicitForall. I would thus like to propose the following formalisation of the ExplicitForall extension: ========================================= ExplicitForall enables the use of the keyword 'forall' to make a type explicitly polymorphic. Syntactically, it would mean the following change to Haskell 98: * 'forall' becomes a reserved word. * '.' (dot) becomes a special (not reserved) operator. * The following syntactic rule changes: type -> 'forall' tyvars '.' type | context '=>' type | ftype ftype -> btype '->' type | btype gendecl -> vars '::' type It does not allow the use of explicitly polymorphic types in any way not already allowed by Haskell 98 for implicitly polymorphic types. ========================================= One thing to note is that I haven't touched the matter of ExistentialQuantification in the above. Syntactically this is a different beast entirely, and could well be handled separately, though it's really an artifact of the way we (by default) write our data type declarations. Using GADT-style declarations, existential quantification goes nicely along with the others by following the same syntactic rules for types, even though from a type system it is of course still quite different from the rest. But with the ordinary Haskell 98 declaration style, we could define the syntactic part of the ExistentialQuantification extension as the following: ========================================= ExistentialQuantification allows data constructors to take existentially quantified arguments. Syntactically, it means the following changes to Haskell98: * 'forall' becomes a reserved word. * '.' (dot) becomes a special (not reserved) operator. * The following syntactic rule changes: constrs -> econstr_1 '|' ... '|' econstr_n econstr -> ['forall' tyvars '.' [context '=>']] constr ========================================= My hope is that you'll all agree with me on the need and rationale for the ExplicitForall extension, and that my proposal for formalisation is good enough for adoption. I feel much less strongly about ExistentialQuantification, and would love to hear some more input on that matter, but I do think it needs to be addressed one way or the other. Thoughts? Cheers, /Niklas [1] http://nibrofun.blogspot.com/2009/06/whats-in-forall.html