Proposal to allow {} instead of () in contexts

Hi - Disregarding my last proposal which involved the use of {} in types, I am wondering if anyone would agree with me that it would be a good idea to use {} instead of () when writing out the context ie: foo :: (Num a, Bar a) => a -> a would become: foo :: {Num a, Bar a} => a -> a and the same for every other situation in the language where a context appears. My reasons are twofold: 1) The context is supposed to be understood (afaiu) as a *set* of constraints not a *tuple* of constraints (ie what relevance does the ordering implied by the tuple notation have here?), so the using of set braces seems mathematically more appropriate 2) It would allow an editor to give the correct fontification for an incomplete type expression. At the moment, if you'd just typed: foo :: (Bar the editor would have no way of knowing if "Bar" is a classcon or a tycon, whereas with: foo :: {Bar the opening brace immediately informs the editor that the following text should be parsed as a context and so it could fontify Bar appropriately. For backwards compatibility the use of () could still be supported - braces don't occur in H98 in the positions I'm proposing to allow them so nothing would be broken. Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com

On 8/23/06, Brian Hulley
Hi - Disregarding my last proposal which involved the use of {} in types, I am wondering if anyone would agree with me that it would be a good idea to use {} instead of () when writing out the context ie:
foo :: (Num a, Bar a) => a -> a
would become:
foo :: {Num a, Bar a} => a -> a
and the same for every other situation in the language where a context appears.
My reasons are twofold:
1) The context is supposed to be understood (afaiu) as a *set* of constraints not a *tuple* of constraints (ie what relevance does the ordering implied by the tuple notation have here?), so the using of set braces seems mathematically more appropriate
I just started programming in Haskell again recently and I cannot even think of a case where any kind of brackets should be necessary. In the report [1], it clearly shows that a context is always followed by "=>." Are the parantheses just used to reduce lookahead requirements for parsers? If so, perhaps the parentheses should be made optional to make them easier to read for people. Plus, then there would not be any tuple vs. set confusion. BTW, at least GHC allows duplicates in the context, like [ foo :: (Num a, Num a) => a -> a ], so I don't know if calling it a "set" is really appropriate either. 2) It would allow an editor to give the correct fontification for an
incomplete type expression. At the moment, if you'd just typed:
foo :: (Bar
the editor would have no way of knowing if "Bar" is a classcon or a tycon, whereas with:
foo :: {Bar
the opening brace immediately informs the editor that the following text should be parsed as a context and so it could fontify Bar appropriately.
What about [ foo :: Bar ] when typing [ foo :: Bar a => a -> a ]? It would be a mistake to require the grouping symbols even when there is only one element in the context. I think that the editor has to be know enough about the program to distinguish classes and type constructors without any grouping symbol requirement. - Brian

On August 23, 2006 5:16 PM, Brian Smith wrote
On 8/23/06, Brian Hulley
wrote: Hi - Disregarding my last proposal which involved the use of {} in types, I am wondering if anyone would agree with me that it would be a good idea to use {} instead of () when writing out the context ie:
foo :: (Num a, Bar a) => a -> a
would become:
foo :: {Num a, Bar a} => a -> a
1) The context is supposed to be understood (afaiu) as a *set*
I just started programming in Haskell again recently and I cannot even think of a case where any kind of brackets should be necessary. In the report [1], it clearly shows that a context is always followed by "=>." Are the parantheses just used to reduce lookahead requirements for parsers? If so, perhaps the parentheses should be made optional to make them easier to read for people. Plus, then there would not be any tuple vs. set confusion.
Also, parens should not be needed in data D = D | E deriving Eq, Ord because a data decl can never be confused with a tuple component. It would certainly be very much neater to not have to use parens just because there is more than one constraint / deriving class. Certainly the current need for parens in these situations seems like a wart and always trips me up.
BTW, at least GHC allows duplicates in the context, like [ foo :: (Num a, Num a) => a -> a ], so I don't know if calling it a "set" is really appropriate either.
I'd argue that this is precisely what makes the above a set rather than a tuple: {Num a, Num a} === {Num a} Also, I'd argue that an error should be given when a constraint is duplicated because it has no meaning thus probably indicates some misunderstanding on the part of the programmer (unless the idea is to pave the way for class aliases where one may want to write code that can compile under different alias environments).
2) It would allow an editor to give the correct fontification for an incomplete type expression. At the moment, if you'd just typed:
foo :: (Bar
the editor would have no way of knowing if "Bar" is a classcon or a tycon, whereas with:
foo :: {Bar
the opening brace immediately informs the editor that the following text should be parsed as a context and so it could fontify Bar appropriately.
What about [ foo :: Bar ] when typing [ foo :: Bar a => a -> a ]? It would be a mistake to require the grouping symbols even when there is only one element in the context. I think that the editor has to be know enough about the program to distinguish classes and type constructors without any grouping symbol requirement.
If braces were used even in the case where there was only one constraint the => would never be needed as in: foo :: {Bar a} a->a so there would be no more characters to type yet the notation would have the advantage that the signature could be understood by itself without requiring the user to have already defined Bar somewhere. I was also thinking that in: foo :: {Ba Ba could be fontified as a classcon to help the user realise that he/she is typing a classcon at that point. However it also could be helpful to only fontify known tycons/classcons and have a different font for "unknown entity", and in practice I suppose it is likely that you'd only start entering signatures etc when the types and classes have already been defined. BTW this also assumes tycons and classcons share the same namespace. If this were changed in future, then it would no longer be able to determine the type/class distinction just by the id (but of course would eventually be known after the => but this is too late for providing syntax help while editing the context itself). Thanks for the idea of making parens optional. I intend to try this as the editor could still save/load files in normal H98 syntax (with parens) yet allow them to be displayed/edited without for added user convenience... :-) Regards, Brian. -- Logic empowers us and Love gives us purpose. Yet still phantoms restless for eras long past, congealed in the present in unthought forms, strive mightily unseen to destroy us. http://www.metamilk.com _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (2)
-
Brian Hulley
-
Brian Smith