Re: Two Proposals
Yes... not quite so well with the “by” variants. What would we say? then group initsBy by x This problem occurs independent of group, does it not? then sortBy by x The solution is to rename sort -- sortByDefault sortBy -- sort but that's hardly appealing. Might be better to live with the problem. Any ideas? I don’t think we can steal “group” as a keyword -- it’s a function exported by Data.List, and I don’t think the benefit justifies the cost. So you are saying you prefer then group to group? Yours, -- P -- .\ Philip Wadler, Professor of Theoretical Computer Science ./\ School of Informatics, University of Edinburgh / \ http://homepages.inf.ed.ac.uk/wadler/ The University of Edinburgh is a charitable body, registered in Scotland, with registration number SC005336. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Two Proposals
For example the following code fragments read well: then group inits then group permutations then group subsequences then group tails Yes... not quite so well with the by variants. What would we say? then group initsBy by x But following the aforementioned naming convention the groupWith function could as well be named as equals. Now this reads well: then group equals by e Good idea. But equals is a terribly over-used word; I think using it would cause confusion. How about equalities, or equivalents :: [a] - [[a]] I don't think we can steal group as a keyword -- it's a function exported by Data.List, and I don't think the benefit justifies the cost. Simon From: George Giorgidze [mailto:giorgi...@gmail.com] Sent: 10 October 2011 23:22 To: Simon Peyton-Jones; GHC Users List; Philip Wadler Subject: Re: Two Proposals A quick thought that came to me after hoogling [a] - [[a]]. The first four functions in the search result are named after what they return (noun in plural) rather than what they do (verb). I am talking about inits, permutations, subsequence and tails. So I thought the following syntax might work as well if (as it is already common) grouping functions are named after what they return. then f then f by e then group f then group f by e For example the following code fragments read well: then group inits then group permutations then group subsequences then group tails Here we use the special identifier group as a verb. I have not told you about the fifth result of the hoogling, the groupWith function. The following really looks ugly: then group groupWith by e But following the aforementioned naming convention the groupWith function could as well be named as equals. Now this reads well: then group equals by e Cheers, George On 2011-Oct-5, at 09:14 , Simon Peyton-Jones wrote: [adding ghc-users] It's not easy, Phil. Do you have any ideas? For the 'then' case the name of the function serves as the verb. One might say then take 4 or then takeWhile by salary 40 For grouping one might like to say the same thing, such as then groupBy by salary but the typing rule is quite different, so we really need a different keyword. We chose the compound keyword then group to avoid needing a whole new keyword (group is treated specially only in tthis context). So you write then group by salary using groupBy Using this order of the pieces for the sorting case is harder. What would one say? then process? Like this? then process by salary 40 using takeWhile Not very nice. One could use a new keyword for grouping theng say, thus: theng groupBy by salary But that is hardly beautiful either. So the current story is not great, but it's the best I could think of. Improvements welcome. Simon | -Original Message- | From: Philip Wadler [mailto:wad...@inf.ed.ac.uk] | Sent: 04 October 2011 18:15 | To: Simon Peyton-Jones; George Giorgidze | Subject: Re: FW: Two Proposals | | George, | | Nice proposal. I like the idea of symmetry, but don't at all like the | idea that f comes before e for 'then' but f comes after e for 'then | group'. Can you rethink it and come up with something even more | symmetric? | | Yours, -- P | | | On Tue, Oct 4, 2011 at 9:23 AM, Simon Peyton-Jones | simo...@microsoft.commailto:simo...@microsoft.com wrote: | FYI | | -Original Message- | From: glasgow-haskell-users-boun...@haskell.orgmailto:glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell- | users-boun...@haskell.org] On Behalf Of George Giorgidze | Sent: 30 September 2011 18:28 | To: glasgow-haskell-users@haskell.orgmailto:glasgow-haskell-users@haskell.org | Subject: Two Proposals | | GHC Users, | | I would like to make to the following two proposals: |* Eliminate the default grouping close from SQL-like comprehensions |* Introduce a GHC extension for list literal overloading | | OK, let me start with the first proposal. | | Currently, the SQL-like comprehension notation (both in its list comprehension | and monad comprehension variants) features the following five clauses: | | then f | then f by e | then group by e | then group using f | then group by e using f | | The first two clauses are used for specifying transformations of type [a] - [a] | (or Monad m = m a- m a for monad comprehensions). The following three | clauses are used for specifying transformations of type [a] - [[a]] (or Monad m, | Functor f = m a - m (f a) for monad comprehensions). See [1] for further | details. | | Note that the third clause does not mention which function is used for grouping. | In this case GHC.Exts.groupWith function is used as a default for list | comprehensions and the mgroupWith function from the MonadGroup class is used | as a default for monad comprehensions. | | I would like to suggest to remove
Fwd: Two Proposals
George, Thanks very much for this. I like your suggestion, which fits the logical structure perfectly; and you've suggested a neat way around the ugliness of 'group groupBy'. I also note that if we aren't so worried about not introducing new keywords, that 'then group' could become 'group'. Yours, -- P On Mon, Oct 10, 2011 at 11:21 PM, George Giorgidze giorgi...@gmail.com wrote: A quick thought that came to me after hoogling [a] - [[a]]. The first four functions in the search result are named after what they return (noun in plural) rather than what they do (verb). I am talking about inits, permutations, subsequence and tails. So I thought the following syntax might work as well if (as it is already common) grouping functions are named after what they return. then f then f by e then group f then group f by e For example the following code fragments read well: then group inits then group permutations then group subsequences then group tails Here we use the special identifier group as a verb. I have not told you about the fifth result of the hoogling, the groupWith function. The following really looks ugly: then group groupWith by e But following the aforementioned naming convention the groupWith function could as well be named as equals. Now this reads well: then group equals by e Cheers, George -- The University of Edinburgh is a charitable body, registered in Scotland, with registration number SC005336. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Fwd: Two Proposals
For some reasons Philip's email was rejected by the mailing list. I am reposting his message. See below. Cheers, George Begin forwarded message: From: Philip Wadler wad...@inf.ed.ac.uk Date: 2011-October-11 11:48:31 GMT+02:00 To: Simon Peyton-Jones simo...@microsoft.com, George Giorgidze george.giorgi...@uni-tuebingen.de Subject: Fwd: Two Proposals FYI. -- P -- Forwarded message -- From: glasgow-haskell-users-ow...@haskell.org Date: Tue, Oct 11, 2011 at 9:28 AM Subject: Re: Two Proposals To: wad...@inf.ed.ac.uk You are not allowed to post to this mailing list, and your message has been automatically rejected. If you think that your messages are being rejected in error, contact the mailing list owner at glasgow-haskell-users-ow...@haskell.org. -- Forwarded message -- From: Philip Wadler wad...@inf.ed.ac.uk To: George Giorgidze giorgi...@gmail.com Date: Tue, 11 Oct 2011 09:28:05 +0100 Subject: Re: Two Proposals George, Thanks very much for this. I like your suggestion, which fits the logical structure perfectly; and you've suggested a neat way around the ugliness of 'group groupBy'. I also note that if we aren't so worried about not introducing new keywords, that 'then group' could become 'group'. Yours, -- P On Mon, Oct 10, 2011 at 11:21 PM, George Giorgidze giorgi...@gmail.com wrote: A quick thought that came to me after hoogling [a] - [[a]]. The first four functions in the search result are named after what they return (noun in plural) rather than what they do (verb). I am talking about inits, permutations, subsequence and tails. So I thought the following syntax might work as well if (as it is already common) grouping functions are named after what they return. then f then f by e then group f then group f by e For example the following code fragments read well: then group inits then group permutations then group subsequences then group tails Here we use the special identifier group as a verb. I have not told you about the fifth result of the hoogling, the groupWith function. The following really looks ugly: then group groupWith by e But following the aforementioned naming convention the groupWith function could as well be named as equals. Now this reads well: then group equals by e Cheers, George On 2011-Oct-5, at 09:14 , Simon Peyton-Jones wrote: [adding ghc-users] It's not easy, Phil. Do you have any ideas? For the 'then' case the name of the function serves as the verb. One might say then take 4 or then takeWhile by salary 40 For grouping one might like to say the same thing, such as then groupBy by salary but the typing rule is quite different, so we really need a different keyword. We chose the compound keyword then group to avoid needing a whole new keyword (group is treated specially only in tthis context). So you write then group by salary using groupBy Using this order of the pieces for the sorting case is harder. What would one say? then process? Like this? then process by salary 40 using takeWhile Not very nice. One could use a new keyword for grouping theng say, thus: theng groupBy by salary But that is hardly beautiful either. So the current story is not great, but it's the best I could think of. Improvements welcome. Simon | -Original Message- | From: Philip Wadler [mailto:wad...@inf.ed.ac.uk] | Sent: 04 October 2011 18:15 | To: Simon Peyton-Jones; George Giorgidze | Subject: Re: FW: Two Proposals | | George, | | Nice proposal. I like the idea of symmetry, but don't at all like the | idea that f comes before e for 'then' but f comes after e for 'then | group'. Can you rethink it and come up with something even more | symmetric? | | Yours, -- P | | | On Tue, Oct 4, 2011 at 9:23 AM, Simon Peyton-Jones | simo...@microsoft.com wrote: | FYI | | -Original Message- | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell- | users-boun...@haskell.org] On Behalf Of George Giorgidze | Sent: 30 September 2011 18:28 | To: glasgow-haskell-users@haskell.org | Subject: Two Proposals | | GHC Users, | | I would like to make to the following two proposals: |* Eliminate the default grouping close from SQL-like comprehensions |* Introduce a GHC extension for list literal overloading | | OK, let me start with the first proposal. | | Currently, the SQL-like comprehension notation (both in its list comprehension | and monad comprehension variants) features the following five clauses: | | then f | then f by e | then group by e | then group using f | then group by e using f | | The first two clauses are used for specifying transformations of type [a] - [a] | (or Monad m = m a- m a for monad comprehensions). The following three | clauses are used for specifying transformations
Re: Two Proposals
On Sun, Oct 9, 2011 at 10:33 PM, George Giorgidze giorgi...@gmail.com wrote: Thanks to all of you for providing feedback on my proposal and for providing alternatives. In this email, I will try to collect all proposals and give pros and cons for each of those (although I will try to provide a good argumentation, some of them might be subjective). Inspired by Simon's and Roman's suggestions I will introduce one more proposal, I am afraid. Proposal (1): my original proposal Pros: * Simple and straightforward generalisation similar to fromInteger and fromString. * Works with arithmetic sequences as well (i.e., for sequences like [1 .. 10], [x .. z], ['a' .. 'z']). Sequences will be desugared as defined in the Haskell standard and the proposed extension would just add the fromList function. Cons: * Performance. I share Roman's concerns. What we are overloading here is somewhat different from integer and string literals. Namely, what I was referring as list literals may feature expressions (e.g., a variable bound elsewhere as in f x = [x,x]) and hence may not be evaluated only once. Maybe I should have called it list notation and not list literals. This proposal would result into runtime overheads associated with conversion of lists. * Programmers may provide partial instances failing at runtime. (BTW. I agree that FromList is much better name than IsList). Proposal (2) by Yitz (with improvements suggested by Gábor) Pros: * Allows partial instances to fail at compile time * Allows writing of instances that convert lists at compile time Cons: * Consensus is emerging that people do not want to unnecessarily tie the lightweight extension of the list notation overloading to the heavyweight extension of Template Haskell. * Not clear how to implement this and what would be the impact on quality of error messages. (The first point is subjective, the second point can be addressed but at this stage I do not know how). Proposal (3) by Roman: the Cons class Pros: * Addresses the runtime conversion issue Cons: * Does not support arithmetic sequences (this can be addressed, see below) Proposal (4) by Simon: avoid classes and desugar to return and mappend Pros: * Addresses the runtime conversion issue * Does not introduce new type classes (at least for the list notation) Cons: * Unnecessarily ties the list notation to the concept of monad. * Does not support arithmetic sequences (this can be addressed, see below) Proposal (5): one more proposal from me (I am afraid) addressing shortcomings of Proposal (3) and Proposal (4). Here is the first attempt to generalise Proposal (4): class Functor f = Pointed f where point :: a - f a with the following (free) pointed law guaranteed by parametricity: fmap f . point = point . f Now the list notation can be desugared as follows: [] = mempty [x,y,z] = point x `mappend` point y `mappend` point z Now this will work for any pointed function that is also a monoid (much larger class of structures than monads that are also monoids). However, Map and Text examples from my original proposal are still ruled out. The following two classes provide as much flexibility as Proposal (1) but avoid going through lists at runtime. class Singleton l where type Elem l singleton :: Elem l - l Now the list notation can be desugarred as follows: [] = mempty [x,y,z] = singleton x `mappend` singleton y `mappend` singleton z Also the following class can be used to desugar arithmetic sequences: class Enum a = GenericEnum f a where genericEnumFrom :: a - f a genericEnumFromThen :: a - a - f a genericEnumFromTo :: a - a - f a genericEnumFromThenTo :: a - a - a - f a as follows: [ x.. ] = genericEnumFrom x [ x,y.. ] = genericEnumFromThen x y [ x..y ] = genericEnumFromTo x y [ x,y..z ] = genericEnumFromThenTo x y z To summarise: * Proposal (5) is slightly more involved one compared to Proposal (1). * Proposal (5) avoids going through lists at runtime and is as flexible as Proposal (1). For me both options are acceptable. But it seems Proposal (5) should be more suitable for DPH folks and other applications (other parallel arrays, e.g., GPU and distributed arrays) where going through lists at runtime is not an option for performance reasons. OK, any thoughts on Proposal (1) vs. Proposal (5)? Is it worth the extra effort to reuse the Monoid instance? It feels a bit contorted to introduce a not-really-generally-useful Singleton class just for the purpose, and then to mappend single-element containers. (I'm not even sure if every type will always have the 'right' Monoid instance, though at the moment I can't think of any counterexamples.) What I think you'd truly want is a class which expresses the thought can have elements added to it (rather than can be combined with others). That's basically what
Re: Two Proposals
For instance, at your day job, the Array type. On Wed, Oct 5, 2011 at 12:23 PM, Roman Leshchinskiy r...@cse.unsw.edu.auwrote: Simon Peyton-Jones wrote: I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
A quick thought that came to me after hoogling [a] - [[a]]. The first four functions in the search result are named after what they return (noun in plural) rather than what they do (verb). I am talking about inits, permutations, subsequence and tails. So I thought the following syntax might work as well if (as it is already common) grouping functions are named after what they return. then f then f by e then group f then group f by e For example the following code fragments read well: then group inits then group permutations then group subsequences then group tails Here we use the special identifier group as a verb. I have not told you about the fifth result of the hoogling, the groupWith function. The following really looks ugly: then group groupWith by e But following the aforementioned naming convention the groupWith function could as well be named as equals. Now this reads well: then group equals by e Cheers, George On 2011-Oct-5, at 09:14 , Simon Peyton-Jones wrote: [adding ghc-users] It's not easy, Phil. Do you have any ideas? For the 'then' case the name of the function serves as the verb. One might say then take 4 or then takeWhile by salary 40 For grouping one might like to say the same thing, such as then groupBy by salary but the typing rule is quite different, so we really need a different keyword. We chose the compound keyword then group to avoid needing a whole new keyword (group is treated specially only in tthis context). So you write then group by salary using groupBy Using this order of the pieces for the sorting case is harder. What would one say? then process? Like this? then process by salary 40 using takeWhile Not very nice. One could use a new keyword for grouping theng say, thus: theng groupBy by salary But that is hardly beautiful either. So the current story is not great, but it's the best I could think of. Improvements welcome. Simon | -Original Message- | From: Philip Wadler [mailto:wad...@inf.ed.ac.uk] | Sent: 04 October 2011 18:15 | To: Simon Peyton-Jones; George Giorgidze | Subject: Re: FW: Two Proposals | | George, | | Nice proposal. I like the idea of symmetry, but don't at all like the | idea that f comes before e for 'then' but f comes after e for 'then | group'. Can you rethink it and come up with something even more | symmetric? | | Yours, -- P | | | On Tue, Oct 4, 2011 at 9:23 AM, Simon Peyton-Jones | simo...@microsoft.com wrote: | FYI | | -Original Message- | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell- | users-boun...@haskell.org] On Behalf Of George Giorgidze | Sent: 30 September 2011 18:28 | To: glasgow-haskell-users@haskell.org | Subject: Two Proposals | | GHC Users, | | I would like to make to the following two proposals: |* Eliminate the default grouping close from SQL-like comprehensions |* Introduce a GHC extension for list literal overloading | | OK, let me start with the first proposal. | | Currently, the SQL-like comprehension notation (both in its list comprehension | and monad comprehension variants) features the following five clauses: | | then f | then f by e | then group by e | then group using f | then group by e using f | | The first two clauses are used for specifying transformations of type [a] - [a] | (or Monad m = m a- m a for monad comprehensions). The following three | clauses are used for specifying transformations of type [a] - [[a]] (or Monad m, | Functor f = m a - m (f a) for monad comprehensions). See [1] for further | details. | | Note that the third clause does not mention which function is used for grouping. | In this case GHC.Exts.groupWith function is used as a default for list | comprehensions and the mgroupWith function from the MonadGroup class is used | as a default for monad comprehensions. | | I would like to suggest to remove the third clause for the following reasons: | * Currently the syntax is asymmetrical. Note that there is the default case for | the 'then group' clause and not for the 'then' clause. | * In the current notation it is not clear which grouping function is used in the | default case | * For many monads including lists it is not clear which function should be | selected as a default (e.g., the groupWith function also does sorting and it is not | clear to me why this should be the default) | * Gets rid of the MonadGroup class. Currently the sole purpose of this class is to | introduce a default grouping function for monad comprehensions. | * Explicit mention of the grouping function would make monad/list | comprehensions much easier to read by making it immediately apparent which | function is used for grouping. | | My second proposal
Re: Two Proposals
Thanks to all of you for providing feedback on my proposal and for providing alternatives. In this email, I will try to collect all proposals and give pros and cons for each of those (although I will try to provide a good argumentation, some of them might be subjective). Inspired by Simon's and Roman's suggestions I will introduce one more proposal, I am afraid. Proposal (1): my original proposal Pros: * Simple and straightforward generalisation similar to fromInteger and fromString. * Works with arithmetic sequences as well (i.e., for sequences like [1 .. 10], [x .. z], ['a' .. 'z']). Sequences will be desugared as defined in the Haskell standard and the proposed extension would just add the fromList function. Cons: * Performance. I share Roman's concerns. What we are overloading here is somewhat different from integer and string literals. Namely, what I was referring as list literals may feature expressions (e.g., a variable bound elsewhere as in f x = [x,x]) and hence may not be evaluated only once. Maybe I should have called it list notation and not list literals. This proposal would result into runtime overheads associated with conversion of lists. * Programmers may provide partial instances failing at runtime. (BTW. I agree that FromList is much better name than IsList). Proposal (2) by Yitz (with improvements suggested by Gábor) Pros: * Allows partial instances to fail at compile time * Allows writing of instances that convert lists at compile time Cons: * Consensus is emerging that people do not want to unnecessarily tie the lightweight extension of the list notation overloading to the heavyweight extension of Template Haskell. * Not clear how to implement this and what would be the impact on quality of error messages. (The first point is subjective, the second point can be addressed but at this stage I do not know how). Proposal (3) by Roman: the Cons class Pros: * Addresses the runtime conversion issue Cons: * Does not support arithmetic sequences (this can be addressed, see below) Proposal (4) by Simon: avoid classes and desugar to return and mappend Pros: * Addresses the runtime conversion issue * Does not introduce new type classes (at least for the list notation) Cons: * Unnecessarily ties the list notation to the concept of monad. * Does not support arithmetic sequences (this can be addressed, see below) Proposal (5): one more proposal from me (I am afraid) addressing shortcomings of Proposal (3) and Proposal (4). Here is the first attempt to generalise Proposal (4): class Functor f = Pointed f where point :: a - f a with the following (free) pointed law guaranteed by parametricity: fmap f . point = point . f Now the list notation can be desugared as follows: [] = mempty [x,y,z] = point x `mappend` point y `mappend` point z Now this will work for any pointed function that is also a monoid (much larger class of structures than monads that are also monoids). However, Map and Text examples from my original proposal are still ruled out. The following two classes provide as much flexibility as Proposal (1) but avoid going through lists at runtime. class Singleton l where type Elem l singleton :: Elem l - l Now the list notation can be desugarred as follows: [] = mempty [x,y,z] = singleton x `mappend` singleton y `mappend` singleton z Also the following class can be used to desugar arithmetic sequences: class Enum a = GenericEnum f a where genericEnumFrom:: a - f a genericEnumFromThen:: a - a - f a genericEnumFromTo :: a - a - f a genericEnumFromThenTo :: a - a - a - f a as follows: [ x.. ] = genericEnumFrom x [ x,y.. ] = genericEnumFromThen x y [ x..y ]= genericEnumFromTo x y [ x,y..z ] = genericEnumFromThenTo x y z To summarise: * Proposal (5) is slightly more involved one compared to Proposal (1). * Proposal (5) avoids going through lists at runtime and is as flexible as Proposal (1). For me both options are acceptable. But it seems Proposal (5) should be more suitable for DPH folks and other applications (other parallel arrays, e.g., GPU and distributed arrays) where going through lists at runtime is not an option for performance reasons. OK, any thoughts on Proposal (1) vs. Proposal (5)? Of course if no consensus is reached we should not implement any of those. Having said that, the reason I like this extension is that it has a potential to subsume and potentially displace two GHC extensions (list literal overloading and the DPH array notation) in future. This rarely happens these days :). Cheers, George P.S. Lennart, asked about defaulting rules and backwards compatibility. Let us keep this in mind and comeback to it after we decide on how to overload the list notation and arithmetic sequences in the first place. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org
Re: Two Proposals
On Oct 6, 2011, at 10:30 AM, Roman Leshchinskiy wrote: Manuel M T Chakravarty wrote: Roman Leshchinskiy: What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Parallel arrays! (I want to get rid of our custom syntax.) Why? Don't you think it is useful to have a visual indication of which data structure you are using and what is going to be evaluated in parallel? I am not a DPH developer :) (just an user), but I thought I would express some of my opinions that are related to your question. Syntactic indications are nice. But why single out DPH arrays? DPH arrays and associated combinators support a very important but only one kind of parallelism, namely nested data parallelism on shared memory multi-core hardware. As parallelism may turn out to be Haskell's killer application we will be dealing with many kinds of parallel data structure supporting different kinds of operations and thus having different types (e.g., GPU arrays, distributed arrays, flat data-parallel arrays). Having a special syntax for each of those would not be manageable. In any case, if we want to get rid of the parallel array syntax, we have to overload list literals, enumerations and list comprehensions. We have the generic monadic desugaring for the latter but recovering an efficient DPH program from that sn't trivial. See Proposal (5) in my previous email. It suggests overloading of list literals and enumerations (I call those arithmetic sequences in that email) without going through lists at runtime. Would that work? As for generic monad comprehension desugaring rules not being efficient enough, I believe it should be possible to define monad instance specific GHC rewrite rules that can rewrite the desugared code as needed. For example, I could imagine how one could rewrite monadic guards into filters, a chain of six zips into zip6 and things like that. I have not tried any of those though. Cheers, George Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
2011/10/5 Simon Peyton-Jones simo...@microsoft.com: | In the spirit of don't let the perfect be the enemy of the good | though, I'm solidly in favor of the original proposal as it is. This is my thought too. George is proposing to extend Haskell's existing mechanism for numeric literals (namely, replace 4 by (fromInteger (4::Integer))), so that it works for lists, just as Lennart did for Strings. One could do more, as Yitz has suggested, but that would be an altogether bigger deal, involving Template Haskell and quite a bit of new design; and if done should apply uniformly to numeric and string literals too. So personally I favour George's general approach as a first step. But here is one thought. In the spirit of monad comprehensions, should we not treat [a,b,c] as short for return a `mappend` return b `mappend` return c so that [a,b,c] syntax is, like [ e | x - xs ] syntax, just short for monadic goop. Then we would not need a new class at all, which would be nice. No, you should not. Most of the types of interest (Sets, Maps, arrays) are not monads. Conflating list comprehensions with monads is a huge mistake, and this would repeat it. -Jan ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Roman Leshchinskiy: Simon Peyton-Jones wrote: I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Parallel arrays! (I want to get rid of our custom syntax.) Manuel ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Manuel M T Chakravarty wrote: Roman Leshchinskiy: What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Parallel arrays! (I want to get rid of our custom syntax.) Why? Don't you think it is useful to have a visual indication of which data structure you are using and what is going to be evaluated in parallel? In any case, if we want to get rid of the parallel array syntax, we have to overload list literals, enumerations and list comprehensions. We have the generic monadic desugaring for the latter but recovering an efficient DPH program from that sn't trivial. Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Roman Leshchinskiy: Manuel M T Chakravarty wrote: Roman Leshchinskiy: What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Parallel arrays! (I want to get rid of our custom syntax.) Why? Don't you think it is useful to have a visual indication of which data structure you are using and what is going to be evaluated in parallel? Whether a computation is parallel depends on the type. That is still the case. In Haskell, it is usually hard to reason about performance without a good understanding of the involved types and their representation. Syntax alone is usually not very helpful. I think it is fine if that is the same for data parallelism. In any case, if we want to get rid of the parallel array syntax, we have to overload list literals, enumerations and list comprehensions. We have the generic monadic desugaring for the latter but recovering an efficient DPH program from that sn't trivial. At ICFP, George suggested that we might use RULES to transform the patterns of generic monadic desugaring into the form that we need for parallel arrays. We need to check whether that really works out, of course. Manuel ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Am Freitag, den 30.09.2011, 19:28 +0200 schrieb George Giorgidze: Basically the idea is to treat list literals like: [1,2,3] as fromList [1,2,3] where class IsList l where type Item l fromList :: [Item l] - l Could we *please* not have classes whose names start with “Is”? We don’t have classes IsNum, IsEq, or IsOrd, so why should we have IsList and IsString? I know that the identifier String is already taken, but please don’t tie an identifier like IsString or IsList to a language feature, so that it’ll be difficult to change it later. Let’s search for a better solution. In the following I give useful instances of the IsList class. […] instance (Ord a) = IsList (Set a) where type Item (Set a) = a fromList = Set.fromList As a set is definitely not a list, the class should better be named differently anyway, shouldn’t it? Don’t know if these issues have already been pointed out, since I didn’t read through the complete thread. Sorry, if they have already. Best wishes, Wolfgang ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: FW: Two Proposals
[adding ghc-users] It's not easy, Phil. Do you have any ideas? For the 'then' case the name of the function serves as the verb. One might say then take 4 or then takeWhile by salary 40 For grouping one might like to say the same thing, such as then groupBy by salary but the typing rule is quite different, so we really need a different keyword. We chose the compound keyword then group to avoid needing a whole new keyword (group is treated specially only in tthis context). So you write then group by salary using groupBy Using this order of the pieces for the sorting case is harder. What would one say? then process? Like this? then process by salary 40 using takeWhile Not very nice. One could use a new keyword for grouping theng say, thus: theng groupBy by salary But that is hardly beautiful either. So the current story is not great, but it's the best I could think of. Improvements welcome. Simon | -Original Message- | From: Philip Wadler [mailto:wad...@inf.ed.ac.uk] | Sent: 04 October 2011 18:15 | To: Simon Peyton-Jones; George Giorgidze | Subject: Re: FW: Two Proposals | | George, | | Nice proposal. I like the idea of symmetry, but don't at all like the | idea that f comes before e for 'then' but f comes after e for 'then | group'. Can you rethink it and come up with something even more | symmetric? | | Yours, -- P | | | On Tue, Oct 4, 2011 at 9:23 AM, Simon Peyton-Jones | simo...@microsoft.com wrote: | FYI | | -Original Message- | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell- | users-boun...@haskell.org] On Behalf Of George Giorgidze | Sent: 30 September 2011 18:28 | To: glasgow-haskell-users@haskell.org | Subject: Two Proposals | | GHC Users, | | I would like to make to the following two proposals: | * Eliminate the default grouping close from SQL-like comprehensions | * Introduce a GHC extension for list literal overloading | | OK, let me start with the first proposal. | | Currently, the SQL-like comprehension notation (both in its list comprehension | and monad comprehension variants) features the following five clauses: | | then f | then f by e | then group by e | then group using f | then group by e using f | | The first two clauses are used for specifying transformations of type [a] - [a] | (or Monad m = m a- m a for monad comprehensions). The following three | clauses are used for specifying transformations of type [a] - [[a]] (or Monad m, | Functor f = m a - m (f a) for monad comprehensions). See [1] for further | details. | | Note that the third clause does not mention which function is used for grouping. | In this case GHC.Exts.groupWith function is used as a default for list | comprehensions and the mgroupWith function from the MonadGroup class is used | as a default for monad comprehensions. | | I would like to suggest to remove the third clause for the following reasons: | * Currently the syntax is asymmetrical. Note that there is the default case for | the 'then group' clause and not for the 'then' clause. | * In the current notation it is not clear which grouping function is used in the | default case | * For many monads including lists it is not clear which function should be | selected as a default (e.g., the groupWith function also does sorting and it is not | clear to me why this should be the default) | * Gets rid of the MonadGroup class. Currently the sole purpose of this class is to | introduce a default grouping function for monad comprehensions. | * Explicit mention of the grouping function would make monad/list | comprehensions much easier to read by making it immediately apparent which | function is used for grouping. | | My second proposal is to introduce the OverloadedLists extension that overloads | list literals. See Section 5.2 in [1] for details. | | Basically the idea is to treat list literals like: | | [1,2,3] | | as | | fromList [1,2,3] | | where | | class IsList l where | type Item l | fromList :: [Item l] - l | | In the following I give useful instances of the IsList class. | | instance IsList [a] where | type Item [a] = a | fromList = id | | instance (Ord a) = IsList (Set a) where | type Item (Set a) = a | fromList = Set.fromList | | instance (Ord k) = IsList (Map k v) where | type Item (Map k v) = (k,v) | fromList = Map.fromList | | instance IsList (IntMap v) where | type Item (IntMap v) = (Int,v) | fromList = IntMap.fromList | | instance IsList Text where | type Item Text = Char | fromList = Text.pack | | As you can see the extension would allow list literals to be used for sets, maps | and integer maps. In addition the suggested OverloadedLists extension would | subsume OverloadedStrings extension (see the instance for Text, for example
RE: Two Proposals
| In the spirit of don't let the perfect be the enemy of the good | though, I'm solidly in favor of the original proposal as it is. This is my thought too. George is proposing to extend Haskell's existing mechanism for numeric literals (namely, replace 4 by (fromInteger (4::Integer))), so that it works for lists, just as Lennart did for Strings. One could do more, as Yitz has suggested, but that would be an altogether bigger deal, involving Template Haskell and quite a bit of new design; and if done should apply uniformly to numeric and string literals too. So personally I favour George's general approach as a first step. But here is one thought. In the spirit of monad comprehensions, should we not treat [a,b,c] as short for return a `mappend` return b `mappend` return c so that [a,b,c] syntax is, like [ e | x - xs ] syntax, just short for monadic goop. Then we would not need a new class at all, which would be nice. That isn't quite what Roman was suggesting (he wanted to supply the 'cons' and 'nil') but it's closer, less head-biased, and it seems to fit the spirit of monad comprehensions. I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. Simon ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Two Proposals
Simon Peyton-Jones wrote: I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
On Wed, Oct 5, 2011 at 8:23 AM, Roman Leshchinskiy r...@cse.unsw.edu.au wrote: Simon Peyton-Jones wrote: I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. What data structures other than lists do we want to construct using list literals? I'm not really sure what the use cases are. Maps and Sets are nice, since we don't have syntax sugar for them. -- Felipe. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
2011/10/5 Simon Peyton-Jones simo...@microsoft.com: | In the spirit of don't let the perfect be the enemy of the good | though, I'm solidly in favor of the original proposal as it is. This is my thought too. George is proposing to extend Haskell's existing mechanism for numeric literals (namely, replace 4 by (fromInteger (4::Integer))), so that it works for lists, just as Lennart did for Strings. One could do more, as Yitz has suggested, but that would be an altogether bigger deal, involving Template Haskell and quite a bit of new design; and if done should apply uniformly to numeric and string literals too. So personally I favour George's general approach as a first step. But here is one thought. In the spirit of monad comprehensions, should we not treat [a,b,c] as short for return a `mappend` return b `mappend` return c so that [a,b,c] syntax is, like [ e | x - xs ] syntax, just short for monadic goop. Then we would not need a new class at all, which would be nice. I prefer the flexibility of George's proposal. Of the examples from his email, the only one this design works for is [a]. That isn't quite what Roman was suggesting (he wanted to supply the 'cons' and 'nil') but it's closer, less head-biased, and it seems to fit the spirit of monad comprehensions. I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. Simon -- Work is punishment for failing to procrastinate effectively. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Hi all, Simon PJ wrote: should we not treat [a,b,c] as short for return a `mappend` return b `mappend` return c [...] I'm not sure if this plan would support [(fred,45), (bill,22)] :: Map String Int. Probably not. Maybe that's a shortcoming... but such Maps are a rather surprising use of list literals. Maybe. But not more surprising than how, say, numeric literals are used in many EDSLs. I also like George's proposal. Best, /Henrik -- Henrik Nilsson School of Computer Science The University of Nottingham n...@cs.nott.ac.uk ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: Two Proposals
I like both George's proposals. Simon | -Original Message- | From: glasgow-haskell-users-boun...@haskell.org [mailto:glasgow-haskell-users- | boun...@haskell.org] On Behalf Of George Giorgidze | Sent: 30 September 2011 18:28 | To: glasgow-haskell-users@haskell.org | Subject: Two Proposals | | GHC Users, | | I would like to make to the following two proposals: | * Eliminate the default grouping close from SQL-like comprehensions | * Introduce a GHC extension for list literal overloading | | OK, let me start with the first proposal. | | Currently, the SQL-like comprehension notation (both in its list comprehension and | monad comprehension variants) features the following five clauses: | | then f | then f by e | then group by e | then group using f | then group by e using f | | The first two clauses are used for specifying transformations of type [a] - [a] (or | Monad m = m a- m a for monad comprehensions). The following three clauses are used | for specifying transformations of type [a] - [[a]] (or Monad m, Functor f = m a - | m (f a) for monad comprehensions). See [1] for further details. | | Note that the third clause does not mention which function is used for grouping. In | this case GHC.Exts.groupWith function is used as a default for list comprehensions | and the mgroupWith function from the MonadGroup class is used as a default for monad | comprehensions. | | I would like to suggest to remove the third clause for the following reasons: | * Currently the syntax is asymmetrical. Note that there is the default case for the | 'then group' clause and not for the 'then' clause. | * In the current notation it is not clear which grouping function is used in the | default case | * For many monads including lists it is not clear which function should be selected | as a default (e.g., the groupWith function also does sorting and it is not clear to | me why this should be the default) | * Gets rid of the MonadGroup class. Currently the sole purpose of this class is to | introduce a default grouping function for monad comprehensions. | * Explicit mention of the grouping function would make monad/list comprehensions | much easier to read by making it immediately apparent which function is used for | grouping. | | My second proposal is to introduce the OverloadedLists extension that overloads list | literals. See Section 5.2 in [1] for details. | | Basically the idea is to treat list literals like: | | [1,2,3] | | as | | fromList [1,2,3] | | where | | class IsList l where | type Item l | fromList :: [Item l] - l | | In the following I give useful instances of the IsList class. | | instance IsList [a] where | type Item [a] = a | fromList = id | | instance (Ord a) = IsList (Set a) where | type Item (Set a) = a | fromList = Set.fromList | | instance (Ord k) = IsList (Map k v) where | type Item (Map k v) = (k,v) | fromList = Map.fromList | | instance IsList (IntMap v) where | type Item (IntMap v) = (Int,v) | fromList = IntMap.fromList | | instance IsList Text where | type Item Text = Char | fromList = Text.pack | | As you can see the extension would allow list literals to be used for sets, maps and | integer maps. In addition the suggested OverloadedLists extension would subsume | OverloadedStrings extension (see the instance for Text, for example). Having said | that, for now, I am not suggesting to remove the OverloadedStrings extension as it | appears to be widely used. | | This extension could also be used for giving data-parallel array literals instead of | the special syntax used currently. | | Unless there is a vocal opposition to the aforementioned two proposals, I would like | to implement them in GHC. Both changes appear to be straightforward to implement. | | Thanks in advance for your feedback. | | Cheers, George | | [1] http://www-db.informatik.uni-tuebingen.de/files/giorgidze/haskell2011.pdf | ___ | Glasgow-haskell-users mailing list | Glasgow-haskell-users@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
George Giorgidze wrote: My second proposal is to introduce the OverloadedLists extension that overloads list literals... I am opposed to this proposal as stated. But I think that with a modification, it can not only be improved, but also solve the problems with the current OverloadedStrings extension. OverloadedStrings - and George's unmodified proposal - change compile time errors into run time errors. Literals with hard-to-find problems are accepted by the compiler and become _|_ at run time. An example of the problem: the xml-types package has an IsString instance for Name. The fromString method parses XML namespaces from XML names and calls error if the parse fails. Without the extension, one would specify the parts using constructors; that is wordy and awkward but checked at compile time. A quasi-quoter could be defined, but that syntax would still be far less convenient in practice than string literals. I agree that we need a way of allowing literals to have some flexibility in their types. But there should be a way for overloading to work at compile time, i.e. more like a quasi-quoter, when needed. Of course, quasi-quoter overloading can also just create an expression that applies a coercion function at run time. So in that sense, quasi-quoter overloading is more general than ad-hoc-polymorphism overloading. In all of George's examples fromList happens to be total, so there isn't an issue having it happen at run time. But if we make this generally available, you can be certain that it will cause problems later on. Just as with IsString, people will not be able to resist the nice syntax, and they will define fromList implementations that are partial. Here is a tentative modification of George's proposal: class IsList l where type Item l fromList :: [Item l] - l listExpQ :: [ExpQ] - ExpQ -- Minimal complete definition: fromList listExpQ = appE (varE (mkName fromList)) . listE If the type of a list literal determines a specific instance of IsList at compile time, use the listExpQ from that instance to interpret the list literal. Otherwise, use the default listExpQ, which is just George's original proposal. An alternative would be to put listExpQ in a separate type class with an IsList constraint. IsString can similarly be extended in a backward compatible way to allow syntax checking at compile time. Here the type could be stringExpQ :: String - ExpQ Numeric literals with Num and Integral can also be extended, though I think the problem is less common for those. Thanks, Yitz ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
George Giorgidze wrote: This extension could also be used for giving data-parallel array literals instead of the special syntax used currently. Unfortunately, it couldn't. DPH array literals don't (and can't really) go through lists. In general, if we are going to overload list literals then forcing the desugaring to always go through lists seems wrong to me. There are plenty of data structures where that might result in a significant performance hit. Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Roman Leshchinskiy wrote: In general, if we are going to overload list literals then forcing the desugaring to always go through lists seems wrong to me. There are plenty of data structures where that might result in a significant performance hit. These are literals. So the lists will almost always be quite short, and they will be evaluated only once. So I don't think there will be that much of a performance hit normally. That said, my extension that allows them to be desugared at compile time would solve that issue if it arises. Regards, Yitz ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Just anecdotally I remember we had this problem with Accelerate. Back when we were using it last Spring for some reason we were forced by the API to at least nominally go through lists on our way to the GPU -- which we sorely hoped were deforested! At times (and somewhat unpredictably), we'd be faced enormous execution times and memory footprints as the runtime tried to create gigantic lists for feeding to Accelerate. Other than that -- I like having a nice literal syntax for other types. But I'm not sure that I construct literals for Sets and IntMaps often enough to profit much... -Ryan On Tue, Oct 4, 2011 at 9:38 AM, Roman Leshchinskiy r...@cse.unsw.edu.auwrote: George Giorgidze wrote: This extension could also be used for giving data-parallel array literals instead of the special syntax used currently. Unfortunately, it couldn't. DPH array literals don't (and can't really) go through lists. In general, if we are going to overload list literals then forcing the desugaring to always go through lists seems wrong to me. There are plenty of data structures where that might result in a significant performance hit. Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
On Tue, Oct 4, 2011 at 3:25 PM, Yitzchak Gale g...@sefer.org wrote: George Giorgidze wrote: My second proposal is to introduce the OverloadedLists extension that overloads list literals... I am opposed to this proposal as stated. But I think that with a modification, it can not only be improved, but also solve the problems with the current OverloadedStrings extension. OverloadedStrings - and George's unmodified proposal - change compile time errors into run time errors. Literals with hard-to-find problems are accepted by the compiler and become _|_ at run time. An example of the problem: the xml-types package has an IsString instance for Name. The fromString method parses XML namespaces from XML names and calls error if the parse fails. Without the extension, one would specify the parts using constructors; that is wordy and awkward but checked at compile time. A quasi-quoter could be defined, but that syntax would still be far less convenient in practice than string literals. I agree that we need a way of allowing literals to have some flexibility in their types. But there should be a way for overloading to work at compile time, i.e. more like a quasi-quoter, when needed. Of course, quasi-quoter overloading can also just create an expression that applies a coercion function at run time. So in that sense, quasi-quoter overloading is more general than ad-hoc-polymorphism overloading. In all of George's examples fromList happens to be total, so there isn't an issue having it happen at run time. But if we make this generally available, you can be certain that it will cause problems later on. Just as with IsString, people will not be able to resist the nice syntax, and they will define fromList implementations that are partial. Here is a tentative modification of George's proposal: class IsList l where type Item l fromList :: [Item l] - l listExpQ :: [ExpQ] - ExpQ -- Minimal complete definition: fromList listExpQ = appE (varE (mkName fromList)) . listE listExpQ doesn't actually use the class's type variable here. You'd have to add a dummy parameter ('l' or preferably 'Proxy l'). That said, this seems like what the Lift class[1] was made for. Maybe: class Lift l = IsList l where fromList :: [Item l] - l and then have GHC apply the function at compile time, during the Template Haskell phase, and then lift and splice the result. That would resolve both your complaint about partial instances (an exception at compile time is a compile error) and Roman's about performance (if it results in a performance hit with some data structures, it'll only be at compile time). I don't know if it would work out mechanically (i.e. whether GHC's internals allow this kind of thing). In the spirit of don't let the perfect be the enemy of the good though, I'm solidly in favor of the original proposal as it is. My only quibble is whether it might not be better called FromList (or FromListLiteral or ...), given that a Map Is not really a List. Since IsString is named the same way, the question is whether consistency or accuracy is more important. [1] http://hackage.haskell.org/packages/archive/template-haskell/2.4.0.0/doc/html/Language-Haskell-TH-Syntax.html If the type of a list literal determines a specific instance of IsList at compile time, use the listExpQ from that instance to interpret the list literal. Otherwise, use the default listExpQ, which is just George's original proposal. An alternative would be to put listExpQ in a separate type class with an IsList constraint. IsString can similarly be extended in a backward compatible way to allow syntax checking at compile time. Here the type could be stringExpQ :: String - ExpQ Numeric literals with Num and Integral can also be extended, though I think the problem is less common for those. Thanks, Yitz ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- Work is punishment for failing to procrastinate effectively. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
2011/10/4 Gábor Lehel illiss...@gmail.com: On Tue, Oct 4, 2011 at 3:25 PM, Yitzchak Gale g...@sefer.org wrote: George Giorgidze wrote: My second proposal is to introduce the OverloadedLists extension that overloads list literals... I am opposed to this proposal as stated. But I think that with a modification, it can not only be improved, but also solve the problems with the current OverloadedStrings extension. OverloadedStrings - and George's unmodified proposal - change compile time errors into run time errors. Literals with hard-to-find problems are accepted by the compiler and become _|_ at run time. An example of the problem: the xml-types package has an IsString instance for Name. The fromString method parses XML namespaces from XML names and calls error if the parse fails. Without the extension, one would specify the parts using constructors; that is wordy and awkward but checked at compile time. A quasi-quoter could be defined, but that syntax would still be far less convenient in practice than string literals. I agree that we need a way of allowing literals to have some flexibility in their types. But there should be a way for overloading to work at compile time, i.e. more like a quasi-quoter, when needed. Of course, quasi-quoter overloading can also just create an expression that applies a coercion function at run time. So in that sense, quasi-quoter overloading is more general than ad-hoc-polymorphism overloading. In all of George's examples fromList happens to be total, so there isn't an issue having it happen at run time. But if we make this generally available, you can be certain that it will cause problems later on. Just as with IsString, people will not be able to resist the nice syntax, and they will define fromList implementations that are partial. Here is a tentative modification of George's proposal: class IsList l where type Item l fromList :: [Item l] - l listExpQ :: [ExpQ] - ExpQ -- Minimal complete definition: fromList listExpQ = appE (varE (mkName fromList)) . listE listExpQ doesn't actually use the class's type variable here. You'd have to add a dummy parameter ('l' or preferably 'Proxy l'). That said, this seems like what the Lift class[1] was made for. Maybe: class Lift l = IsList l where fromList :: [Item l] - l and then have GHC apply the function at compile time, during the Template Haskell phase, and then lift and splice the result. That would resolve both your complaint about partial instances (an exception at compile time is a compile error) and Roman's about performance (if it results in a performance hit with some data structures, it'll only be at compile time). I don't know if it would work out mechanically (i.e. whether GHC's internals allow this kind of thing). In the spirit of don't let the perfect be the enemy of the good though, I'm solidly in favor of the original proposal as it is. My only quibble is whether it might not be better called FromList (or FromListLiteral or ...), given that a Map Is not really a List. Since IsString is named the same way, the question is whether consistency or accuracy is more important. (Of course I mean that if we can get something better, great, but the original proposal is a lot better than nothing - not that I would actually prefer the original to something better than it.) [1] http://hackage.haskell.org/packages/archive/template-haskell/2.4.0.0/doc/html/Language-Haskell-TH-Syntax.html If the type of a list literal determines a specific instance of IsList at compile time, use the listExpQ from that instance to interpret the list literal. Otherwise, use the default listExpQ, which is just George's original proposal. An alternative would be to put listExpQ in a separate type class with an IsList constraint. IsString can similarly be extended in a backward compatible way to allow syntax checking at compile time. Here the type could be stringExpQ :: String - ExpQ Numeric literals with Num and Integral can also be extended, though I think the problem is less common for those. Thanks, Yitz ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- Work is punishment for failing to procrastinate effectively. -- Work is punishment for failing to procrastinate effectively. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
On Fri, Sep 30, 2011 at 7:28 PM, George Giorgidze giorgi...@gmail.com wrote: GHC Users, I would like to make to the following two proposals: * Eliminate the default grouping close from SQL-like comprehensions * Introduce a GHC extension for list literal overloading OK, let me start with the first proposal. Currently, the SQL-like comprehension notation (both in its list comprehension and monad comprehension variants) features the following five clauses: then f then f by e then group by e then group using f then group by e using f The first two clauses are used for specifying transformations of type [a] - [a] (or Monad m = m a- m a for monad comprehensions). The following three clauses are used for specifying transformations of type [a] - [[a]] (or Monad m, Functor f = m a - m (f a) for monad comprehensions). See [1] for further details. Note that the third clause does not mention which function is used for grouping. In this case GHC.Exts.groupWith function is used as a default for list comprehensions and the mgroupWith function from the MonadGroup class is used as a default for monad comprehensions. I would like to suggest to remove the third clause for the following reasons: * Currently the syntax is asymmetrical. Note that there is the default case for the 'then group' clause and not for the 'then' clause. * In the current notation it is not clear which grouping function is used in the default case * For many monads including lists it is not clear which function should be selected as a default (e.g., the groupWith function also does sorting and it is not clear to me why this should be the default) * Gets rid of the MonadGroup class. Currently the sole purpose of this class is to introduce a default grouping function for monad comprehensions. * Explicit mention of the grouping function would make monad/list comprehensions much easier to read by making it immediately apparent which function is used for grouping. My second proposal is to introduce the OverloadedLists extension that overloads list literals. See Section 5.2 in [1] for details. Basically the idea is to treat list literals like: [1,2,3] as fromList [1,2,3] where class IsList l where type Item l fromList :: [Item l] - l In the following I give useful instances of the IsList class. instance IsList [a] where type Item [a] = a fromList = id instance (Ord a) = IsList (Set a) where type Item (Set a) = a fromList = Set.fromList instance (Ord k) = IsList (Map k v) where type Item (Map k v) = (k,v) fromList = Map.fromList instance IsList (IntMap v) where type Item (IntMap v) = (Int,v) fromList = IntMap.fromList instance IsList Text where type Item Text = Char fromList = Text.pack ...one more thought: would this work together with instances of Enum? Could you write: letters :: Text letters = ['a'..'z'] As you can see the extension would allow list literals to be used for sets, maps and integer maps. In addition the suggested OverloadedLists extension would subsume OverloadedStrings extension (see the instance for Text, for example). Having said that, for now, I am not suggesting to remove the OverloadedStrings extension as it appears to be widely used. This extension could also be used for giving data-parallel array literals instead of the special syntax used currently. Unless there is a vocal opposition to the aforementioned two proposals, I would like to implement them in GHC. Both changes appear to be straightforward to implement. Thanks in advance for your feedback. Cheers, George [1] http://www-db.informatik.uni-tuebingen.de/files/giorgidze/haskell2011.pdf ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users -- Work is punishment for failing to procrastinate effectively. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
Yitzchak Gale wrote: Roman Leshchinskiy wrote: In general, if we are going to overload list literals then forcing the desugaring to always go through lists seems wrong to me. There are plenty of data structures where that might result in a significant performance hit. These are literals. So the lists will almost always be quite short, and they will be evaluated only once. So I don't think there will be that much of a performance hit normally. Calling them literals is misleading, IMO. They won't necessarily be only evaluated once: f x = [x] In DPH, it wasn't uncommon for certain benchmarks to spend 90% of the time constructing arrays from [:x,y,z:] terms until we made a significant effort to ensure that this doesn't happen. This is the only real data point related to this that I have but it does indicate that making the desugaring efficient is quite important. That said, my extension that allows them to be desugared at compile time would solve that issue if it arises. Personally, I don't like having desugaring depend on TH at all. I'm not sure think there is a real need for it. This would, IMO, already be better than fromList wrt efficiency: class Cons a where type Elem a empty :: a cons :: Elem a - a - a Roman ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Two Proposals
GHC Users, I would like to make to the following two proposals: * Eliminate the default grouping close from SQL-like comprehensions * Introduce a GHC extension for list literal overloading OK, let me start with the first proposal. Currently, the SQL-like comprehension notation (both in its list comprehension and monad comprehension variants) features the following five clauses: then f then f by e then group by e then group using f then group by e using f The first two clauses are used for specifying transformations of type [a] - [a] (or Monad m = m a- m a for monad comprehensions). The following three clauses are used for specifying transformations of type [a] - [[a]] (or Monad m, Functor f = m a - m (f a) for monad comprehensions). See [1] for further details. Note that the third clause does not mention which function is used for grouping. In this case GHC.Exts.groupWith function is used as a default for list comprehensions and the mgroupWith function from the MonadGroup class is used as a default for monad comprehensions. I would like to suggest to remove the third clause for the following reasons: * Currently the syntax is asymmetrical. Note that there is the default case for the 'then group' clause and not for the 'then' clause. * In the current notation it is not clear which grouping function is used in the default case * For many monads including lists it is not clear which function should be selected as a default (e.g., the groupWith function also does sorting and it is not clear to me why this should be the default) * Gets rid of the MonadGroup class. Currently the sole purpose of this class is to introduce a default grouping function for monad comprehensions. * Explicit mention of the grouping function would make monad/list comprehensions much easier to read by making it immediately apparent which function is used for grouping. My second proposal is to introduce the OverloadedLists extension that overloads list literals. See Section 5.2 in [1] for details. Basically the idea is to treat list literals like: [1,2,3] as fromList [1,2,3] where class IsList l where type Item l fromList :: [Item l] - l In the following I give useful instances of the IsList class. instance IsList [a] where type Item [a] = a fromList = id instance (Ord a) = IsList (Set a) where type Item (Set a) = a fromList = Set.fromList instance (Ord k) = IsList (Map k v) where type Item (Map k v) = (k,v) fromList = Map.fromList instance IsList (IntMap v) where type Item (IntMap v) = (Int,v) fromList = IntMap.fromList instance IsList Text where type Item Text = Char fromList = Text.pack As you can see the extension would allow list literals to be used for sets, maps and integer maps. In addition the suggested OverloadedLists extension would subsume OverloadedStrings extension (see the instance for Text, for example). Having said that, for now, I am not suggesting to remove the OverloadedStrings extension as it appears to be widely used. This extension could also be used for giving data-parallel array literals instead of the special syntax used currently. Unless there is a vocal opposition to the aforementioned two proposals, I would like to implement them in GHC. Both changes appear to be straightforward to implement. Thanks in advance for your feedback. Cheers, George [1] http://www-db.informatik.uni-tuebingen.de/files/giorgidze/haskell2011.pdf ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Two Proposals
What are the defaulting rules for IsList? It needs to be backwards compatible. -- Lennart (iPhone) On Sep 30, 2011, at 19:28, George Giorgidze giorgi...@gmail.com wrote: GHC Users, I would like to make to the following two proposals: * Eliminate the default grouping close from SQL-like comprehensions * Introduce a GHC extension for list literal overloading OK, let me start with the first proposal. Currently, the SQL-like comprehension notation (both in its list comprehension and monad comprehension variants) features the following five clauses: then f then f by e then group by e then group using f then group by e using f The first two clauses are used for specifying transformations of type [a] - [a] (or Monad m = m a- m a for monad comprehensions). The following three clauses are used for specifying transformations of type [a] - [[a]] (or Monad m, Functor f = m a - m (f a) for monad comprehensions). See [1] for further details. Note that the third clause does not mention which function is used for grouping. In this case GHC.Exts.groupWith function is used as a default for list comprehensions and the mgroupWith function from the MonadGroup class is used as a default for monad comprehensions. I would like to suggest to remove the third clause for the following reasons: * Currently the syntax is asymmetrical. Note that there is the default case for the 'then group' clause and not for the 'then' clause. * In the current notation it is not clear which grouping function is used in the default case * For many monads including lists it is not clear which function should be selected as a default (e.g., the groupWith function also does sorting and it is not clear to me why this should be the default) * Gets rid of the MonadGroup class. Currently the sole purpose of this class is to introduce a default grouping function for monad comprehensions. * Explicit mention of the grouping function would make monad/list comprehensions much easier to read by making it immediately apparent which function is used for grouping. My second proposal is to introduce the OverloadedLists extension that overloads list literals. See Section 5.2 in [1] for details. Basically the idea is to treat list literals like: [1,2,3] as fromList [1,2,3] where class IsList l where type Item l fromList :: [Item l] - l In the following I give useful instances of the IsList class. instance IsList [a] where type Item [a] = a fromList = id instance (Ord a) = IsList (Set a) where type Item (Set a) = a fromList = Set.fromList instance (Ord k) = IsList (Map k v) where type Item (Map k v) = (k,v) fromList = Map.fromList instance IsList (IntMap v) where type Item (IntMap v) = (Int,v) fromList = IntMap.fromList instance IsList Text where type Item Text = Char fromList = Text.pack As you can see the extension would allow list literals to be used for sets, maps and integer maps. In addition the suggested OverloadedLists extension would subsume OverloadedStrings extension (see the instance for Text, for example). Having said that, for now, I am not suggesting to remove the OverloadedStrings extension as it appears to be widely used. This extension could also be used for giving data-parallel array literals instead of the special syntax used currently. Unless there is a vocal opposition to the aforementioned two proposals, I would like to implement them in GHC. Both changes appear to be straightforward to implement. Thanks in advance for your feedback. Cheers, George [1] http://www-db.informatik.uni-tuebingen.de/files/giorgidze/haskell2011.pdf ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users