
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

| I would thus like to propose the following formalisation of the | ExplicitForall extension: What you suggest would be fine with me. Presumably ExplicitForall would be implied by RankNTypes and the other extensions? There is a danger of having too *many* choices. (http://www.joelonsoftware.com/items/2006/11/21.html) In particular, you might consider making ScopedTypeVariables synonymous with ExplicitForAll. Once you have given up the keyword, it seems a shame not to allow lexically scoped type variables! On ExistentialQuantification, I personally think we should deprecate the entire construct, suggesting GADT-style syntax instead. If you can form a consensus, go for it. Simon

What you suggest would be fine with me. Presumably ExplicitForall would be implied by RankNTypes and the other extensions?
Yes, that's the idea. Rank2Types, RankNTypes, PolymorphicComponents, ScopedTypeVariables and LiberalTypeSynonyms would all imply ExplicitForall.
There is a danger of having too *many* choices. (http://www.joelonsoftware.com/items/2006/11/21.html) In particular, you might consider making ScopedTypeVariables synonymous with ExplicitForAll. Once you have given up the keyword, it seems a shame not to allow lexically scoped type variables!
While I agree with you (and Joel) in principle, I think this is the wrong level to hold that discussion. I think the long-term solution should be to keep the registered extensions cleanly separated, and instead supply extension *groups* as a way to limit choice. -fglasgow-exts has fit that niche admirably for a long time, I think a lot of people just use that without thinking twice about what particular extensions they actually use, and nothing wrong with that. I think the move towards LANGUAGE pragmas instead of compiler options is a good one from a standardisation and implementation point of view, but to avoid tedium and unnecessary choice for the programmer I strongly feel that extension groups need to be introduced at this level too. But as I said, that's for a different discussion...
On ExistentialQuantification, I personally think we should deprecate the entire construct, suggesting GADT-style syntax instead.
+1, though I was afraid to suggest something that radical. I might write a separate proposal for that then, to keep the discussion here focused on ExplicitForall.
If you can form a consensus, go for it.
Alright, let's set an actual discussion period of 2 weeks for ExplicitForall. If there is no opposition by then, we can add ExplicitForall to the registered extensions in cabal as a first step. Cheers, /Niklas

Alright, let's set an actual discussion period of 2 weeks for ExplicitForall. If there is no opposition by then, we can add ExplicitForall to the registered extensions in cabal as a first step.
Slightly more than two weeks later, there has been no voices against and at least a few in favor. The attached patch for Cabal adds ExplicitForall to the Extension datatype, with documentation, and adds it to knownExtensions. Cheers, /Niklas

On Thu, Jul 23, 2009 at 7:36 AM, Niklas Broberg
Alright, let's set an actual discussion period of 2 weeks for ExplicitForall. If there is no opposition by then, we can add ExplicitForall to the registered extensions in cabal as a first step.
Slightly more than two weeks later, there has been no voices against and at least a few in favor.
Huh. I guess I forgot I could reply? In favour I am. (Even if I do live in the US. </spelling-related-joke>)
participants (3)
-
Niklas Broberg
-
Samuel Bronson
-
Simon Peyton-Jones