Proposal for stand-alone deriving declarations?

On http://hackage.haskell.org/trac/haskell-prime/wiki/ DerivedInstances it says: "- There is no way to derive an instance of a class for a data type that is defined elsewhere (in another module)." Though there is no proposal to fix this. Would such a proposal be appropriate for Haskell'? If so, I propose to add a top-level declaration on the form: 'deriving' qtycls 'for' qtycon which produces the same instance as a deriving clause in the declaration of the datatype or newtype would. I have recently (thanks to the GHC Hackathon) implemented this in GHC. /Björn

Thanks for doing this. Is this the syntax we settled on? I remember we discussed it at some length S | -----Original Message----- | From: haskell-prime-bounces@haskell.org [mailto:haskell-prime-bounces@haskell.org] On Behalf Of | Bjorn Bringert | Sent: 05 October 2006 09:05 | To: haskell-prime@haskell.org | Subject: Proposal for stand-alone deriving declarations? | | On http://hackage.haskell.org/trac/haskell-prime/wiki/ | DerivedInstances it says: | | "- There is no way to derive an instance of a class for a data type | that is defined elsewhere (in another module)." | | Though there is no proposal to fix this. Would such a proposal be | appropriate for Haskell'? | | | If so, I propose to add a top-level declaration on the form: | | 'deriving' qtycls 'for' qtycon | | which produces the same instance as a deriving clause in the | declaration of the datatype or newtype would. | | | I have recently (thanks to the GHC Hackathon) implemented this in GHC. | | /Björn | | _______________________________________________ | Haskell-prime mailing list | Haskell-prime@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-prime

What I implemented in GHC is an extension of the proposal below. The proposal just mentions: deriving Class for Type In GHC I also added a form for newtype deriving of multi-parameter type classes: deriving (Class t1 ... tn) for Type I think that it's close to what we ended up with when talking about it at the Hackathon. My intuition about this syntax is that except for the "for Type" part, it looks the same as a normal deriving clause. The "for" part is just there to connect it to a data/newtype declaration. This lets it pretty much use the normal code for deriving declarations. Stand-alone deriving declarations are currently a little bit weaker than normal deriving clauses, since the current implementation does not let you reference the type arguments of a newtype in the arguments of an MPTC. See my response to Bulat on cvs-ghc@haskell.org for more details. /Björn On 5 okt 2006, at 10.36, Simon Peyton-Jones wrote:
Thanks for doing this.
Is this the syntax we settled on? I remember we discussed it at some length
S
| -----Original Message----- | From: haskell-prime-bounces@haskell.org [mailto:haskell-prime- bounces@haskell.org] On Behalf Of | Bjorn Bringert | Sent: 05 October 2006 09:05 | To: haskell-prime@haskell.org | Subject: Proposal for stand-alone deriving declarations? | | On http://hackage.haskell.org/trac/haskell-prime/wiki/ | DerivedInstances it says: | | "- There is no way to derive an instance of a class for a data type | that is defined elsewhere (in another module)." | | Though there is no proposal to fix this. Would such a proposal be | appropriate for Haskell'? | | | If so, I propose to add a top-level declaration on the form: | | 'deriving' qtycls 'for' qtycon | | which produces the same instance as a deriving clause in the | declaration of the datatype or newtype would. | | | I have recently (thanks to the GHC Hackathon) implemented this in GHC. | | /Björn | | _______________________________________________ | Haskell-prime mailing list | Haskell-prime@haskell.org | http://www.haskell.org/mailman/listinfo/haskell-prime

Bjorn Bringert:
On http://hackage.haskell.org/trac/haskell-prime/wiki/ DerivedInstances it says:
"- There is no way to derive an instance of a class for a data type that is defined elsewhere (in another module)."
Though there is no proposal to fix this. Would such a proposal be appropriate for Haskell'?
I think this would be a useful feature to have. (I certainly wished to have independent deriving declarations many times when writing Haskell code.) It also seems to be a fairly small, well understood extension.
If so, I propose to add a top-level declaration on the form:
'deriving' qtycls 'for' qtycon
which produces the same instance as a deriving clause in the declaration of the datatype or newtype would.
I guess, the right way to go about this would be to say that independent deriving declarations are the fundamental way of deriving a type class. The original form of a deriving clause at a data/newtype declaration is, then, just a syntactic shorthand for a data/newtype declaration plus a bunch of independent deriving declarations. What is not so nice is that you take a new keyword ('for'), which is quite likely to have been used as a variable name in existing code. (Or does it work out to use one of the 'special' names here?) I think it would be useful to write the proposal in complete detail up on the Haskell' wiki. Manuel

| What is not so nice is that you take a new keyword ('for'), which is | quite likely to have been used as a variable name in existing code. (Or | does it work out to use one of the 'special' names here?) The latter is what Bjorn has done. That is, 'for' is only special in this one context. You can use it freely otherwise. As I understand it anyway. | I think it would be useful to write the proposal in complete detail up | on the Haskell' wiki. Yes please. Bjorn? (It may just be a qn of transcribing the user manual stuff you have written.) S

Simon Peyton-Jones wrote:
| What is not so nice is that you take a new keyword ('for'), which is | quite likely to have been used as a variable name in existing code. (Or | does it work out to use one of the 'special' names here?)
The latter is what Bjorn has done. That is, 'for' is only special in this one context. You can use it freely otherwise. As I understand it anyway.
Yes. There is even a "for" function somewhere in the libraries (or was it the testsuite, can't remeber), which tripped up one of my early versions, before I had remembered to make "for" as a special ID in the parser.
| I think it would be useful to write the proposal in complete detail up | on the Haskell' wiki.
Yes please. Bjorn? (It may just be a qn of transcribing the user manual stuff you have written.)
Sure. It seems that I have to be on the committee to write to the Wiki. Can I join it? /Björn

Hello,
A question about the syntax: would there be a problem if we made the
'deriving' declaration look like an instance? Then we would not need
the special identifier 'for', and also we have a more standard looking
notation. I am thinking something like:
deriving Show SomeType
deriving Eq (AnotherType a)
-Iavor
On 10/5/06, Björn Bringert
Simon Peyton-Jones wrote:
| What is not so nice is that you take a new keyword ('for'), which is | quite likely to have been used as a variable name in existing code. (Or | does it work out to use one of the 'special' names here?)
The latter is what Bjorn has done. That is, 'for' is only special in this one context. You can use it freely otherwise. As I understand it anyway.
Yes. There is even a "for" function somewhere in the libraries (or was it the testsuite, can't remeber), which tripped up one of my early versions, before I had remembered to make "for" as a special ID in the parser.
| I think it would be useful to write the proposal in complete detail up | on the Haskell' wiki.
Yes please. Bjorn? (It may just be a qn of transcribing the user manual stuff you have written.)
Sure. It seems that I have to be on the committee to write to the Wiki. Can I join it?
/Björn _______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime

We considered that syntax, but decided against it. Stand-alone deriving declarations are made to be as similar as possible to the current deriving mechanism, rather than be similar to instance declarations. The basic reason for maintaining a syntactic distinction between instance declarations and deriving declarations is to make the programmer aware of the restrictions of the deriving mechanism. These are some things that make deriving declarations different from instance declarations: - You can only derive instances for data types and newtypes. - For deriving declarations, the compiler figures out the constraints, whereas the programmer writes them for instance declarations. - In GHC, you can declare non-Haskell98 instances such as Eq (C X) where X is a concrete type, but you can't do deriving for them. - When deriving instances of multi-parameter type classes (again non- standard), the newtype for which the deriving is made must be the last argument to the class. If the syntax were "deriving (Class T1 ... Tn)", it might not be clear to the reader what type the deriving is for. I can't see any technical reason not to do as you propose. One advantage would be that it makes it possible to fully subsume GHC's current deriving extensions (though there are other ways to do this, see my recent e-mail to ghc-cvs). One slight disadvantage is that it does require a bit more footwork in the compiler to figure out which type to do the deriving for. /Björn On 5 okt 2006, at 19.58, Iavor Diatchki wrote:
Hello, A question about the syntax: would there be a problem if we made the 'deriving' declaration look like an instance? Then we would not need the special identifier 'for', and also we have a more standard looking notation. I am thinking something like: deriving Show SomeType deriving Eq (AnotherType a) -Iavor
On 10/5/06, Björn Bringert
wrote: Simon Peyton-Jones wrote:
| What is not so nice is that you take a new keyword ('for'), which is | quite likely to have been used as a variable name in existing code. (Or | does it work out to use one of the 'special' names here?)
The latter is what Bjorn has done. That is, 'for' is only special in this one context. You can use it freely otherwise. As I understand it anyway.
Yes. There is even a "for" function somewhere in the libraries (or was it the testsuite, can't remeber), which tripped up one of my early versions, before I had remembered to make "for" as a special ID in the parser.
| I think it would be useful to write the proposal in complete detail up | on the Haskell' wiki.
Yes please. Bjorn? (It may just be a qn of transcribing the user manual stuff you have written.)
Sure. It seems that I have to be on the committee to write to the Wiki. Can I join it?
/Björn _______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime

Off-list, Greg Fitzgerald pointed out that:
Those wanting to use the SYB library may want to write something like this for every datatype in their heirarchy:
deriving Data, Typable for Person, Team, Department, Company
That seems like a useful extension to me, and the meaning is obvious. This would as far as I can tell not be possible (or at least not readable) without the "for". /Björn On 5 okt 2006, at 20.58, Bjorn Bringert wrote:
We considered that syntax, but decided against it. Stand-alone deriving declarations are made to be as similar as possible to the current deriving mechanism, rather than be similar to instance declarations. The basic reason for maintaining a syntactic distinction between instance declarations and deriving declarations is to make the programmer aware of the restrictions of the deriving mechanism.
These are some things that make deriving declarations different from instance declarations:
- You can only derive instances for data types and newtypes. - For deriving declarations, the compiler figures out the constraints, whereas the programmer writes them for instance declarations. - In GHC, you can declare non-Haskell98 instances such as Eq (C X) where X is a concrete type, but you can't do deriving for them. - When deriving instances of multi-parameter type classes (again non-standard), the newtype for which the deriving is made must be the last argument to the class. If the syntax were "deriving (Class T1 ... Tn)", it might not be clear to the reader what type the deriving is for.
I can't see any technical reason not to do as you propose. One advantage would be that it makes it possible to fully subsume GHC's current deriving extensions (though there are other ways to do this, see my recent e-mail to ghc-cvs). One slight disadvantage is that it does require a bit more footwork in the compiler to figure out which type to do the deriving for.
/Björn
On 5 okt 2006, at 19.58, Iavor Diatchki wrote:
Hello, A question about the syntax: would there be a problem if we made the 'deriving' declaration look like an instance? Then we would not need the special identifier 'for', and also we have a more standard looking notation. I am thinking something like: deriving Show SomeType deriving Eq (AnotherType a) -Iavor
On 10/5/06, Björn Bringert
wrote: Simon Peyton-Jones wrote:
| What is not so nice is that you take a new keyword ('for'), which is | quite likely to have been used as a variable name in existing code. (Or | does it work out to use one of the 'special' names here?)
The latter is what Bjorn has done. That is, 'for' is only special in this one context. You can use it freely otherwise. As I understand it anyway.
Yes. There is even a "for" function somewhere in the libraries (or was it the testsuite, can't remeber), which tripped up one of my early versions, before I had remembered to make "for" as a special ID in the parser.
| I think it would be useful to write the proposal in complete detail up | on the Haskell' wiki.
Yes please. Bjorn? (It may just be a qn of transcribing the user manual stuff you have written.)
Sure. It seems that I have to be on the committee to write to the Wiki. Can I join it?
/Björn _______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
_______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime

On Thu, Oct 05, 2006 at 08:58:28PM +0200, Bjorn Bringert wrote:
- When deriving instances of multi-parameter type classes (again non- standard), the newtype for which the deriving is made must be the last argument to the class. If the syntax were "deriving (Class T1 ... Tn)", it might not be clear to the reader what type the deriving is for.
I have run into this restriction multiple times, and since it only arises due to the syntax, it would be good to fix that too with any proposed change to the deriving syntax. A related issue is that you currently cannot 'co-derive' a multiparameter typeclass among multiple newtype definitions. such as the following:
class SetLike m k where insert :: k -> m -> m ...
instance SetLike IntSet Int where ...
newtype Id = Id Int
newtype IdSet = IdSet IntSet
now, ideally you should be able to derive MapLike (IdMap v) Id v, but there is no way to do it with the current syntax. if we make the instance we are using to derive the newtypes instance from explicit however, it solves both problems nicely. allow toplevel definitions like the following:
deriving (SetLike IntSet Int => SetLike IdSet Id)
John -- John Meacham - ⑆repetae.net⑆john⑈

"Iavor Diatchki"
A question about the syntax: would there be a problem if we made the 'deriving' declaration look like an instance?
And you might as well keep the 'instance' keyword when instantiating, even if the instance is derived? Seems more consistent to me ('deriving' feels more like a kind of parameter to 'data' declarations) and avoids introducing a new keyword, except in the context of instance declarations.
deriving Show SomeType deriving Eq (AnotherType a)
instance Show Sometype derived instance Eq (AnotherType a) where (==) = ... -k -- If I haven't seen further, it is by standing in the footprints of giants

Ketil Malde wrote:
"Iavor Diatchki"
writes: A question about the syntax: would there be a problem if we made the 'deriving' declaration look like an instance?
And you might as well keep the 'instance' keyword when instantiating, even if the instance is derived? Seems more consistent to me ('deriving' feels more like a kind of parameter to 'data' declarations) and avoids introducing a new keyword, except in the context of instance declarations.
deriving Show SomeType deriving Eq (AnotherType a)
instance Show Sometype derived instance Eq (AnotherType a) where (==) = ...
-k
One problem with this is that there is no context in the declaration, e.g.: instance Eq (AnotherType a) derived Although the generated instance does have one: instance Eq a => Eq (AnotherType a) where ... (depending on how a is used by the data constructors of AnotherType). This goes back to the argument I was making earlier about the differences between instance and deriving declarations. /Björn

On Thu, Oct 05, 2006 at 10:05:20AM +0200, Bjorn Bringert wrote:
I propose to add a top-level declaration on the form:
'deriving' qtycls 'for' qtycon
which produces the same instance as a deriving clause in the declaration of the datatype or newtype would.
If this is added (whatever the syntax), you'd also want to permit multiple identical derived instances. The main use for this seems to be when a module defining a data type lacks an instance you want, and for some reason you can't get the original module changed. (It could also be used to derive instances of a class you just defined for existing newtypes, but that seems rarer.) Several modules might use this workaround for the same base module, and you wouldn't want those modules to be incompatible.

The main use for this seems to be when a module defining a data type lacks an instance you want, and for some reason you can't get the original module changed.
If you continue this line of reasoning: 1. The only reason a module can not be changed is that it is in some library as opposed to your own code. 2. The only instances that can be derived are for Prelude classes. 3. These classes are already known in library modules, so they could have been derived there. 4. The fact that they are not unnecessarily reduces the usefulness of the library, and could therefore be considered a bug. 5. In fact, looking at the standard libraries, they already provide instances for all relevant Prelude classes. This leaves me to wonder what stand-alone deriving is actually good for, only newtypes? Twan

On 7 okt 2006, at 16.44, Twan van Laarhoven wrote:
The main use for this seems to be when a module defining a data type lacks an instance you want, and for some reason you can't get the original module changed.
If you continue this line of reasoning: 1. The only reason a module can not be changed is that it is in some library as opposed to your own code. 2. The only instances that can be derived are for Prelude classes.
In for example GHC, this is not entirely true. GHC can derive instances of Typeable and Data, and more could be added in the future. Also, compilers could conceivably allow user-defined deriving.
3. These classes are already known in library modules, so they could have been derived there. 4. The fact that they are not unnecessarily reduces the usefulness of the library, and could therefore be considered a bug.
Existing libraries might not know about which classes future compiler versions can derive. Also, a library that wants to work with multiple compilers cannot have deriving classes for non-standard classes.
5. In fact, looking at the standard libraries, they already provide instances for all relevant Prelude classes.
There are plenty of libraries which are not standard libraries.
This leaves me to wonder what stand-alone deriving is actually good for, only newtypes?
I agree that it's not exactly something you will use every day, but when you do need it, it can save a lot of work. Imagine defining standard Show and Read, or Data and Typeable, instances manually for some rich family of data types. Besides, as Manuel pointed out, stand-alone deriving generalizes the current deriving clauses. Thus it can be seen as a way to remove an unnecessary restriction. /Björn

| > I propose to add a top-level declaration on the form: | > | > 'deriving' qtycls 'for' qtycon | > | > which produces the same instance as a deriving clause in the | > declaration of the datatype or newtype would. | | If this is added (whatever the syntax), you'd also want to permit multiple | identical derived instances. Perhaps so. This might generate duplicate code (one for each decl) but it'd be guaranteed identical since it's generated by a deriving clause. It'd require some .hi file support, to record that an instance came from a 'deriving' decl. I'm inclined to wait until someone asks for it "for real" as it were. Simon

On Mon, Oct 09, 2006 at 01:19:38PM +0100, Simon Peyton-Jones wrote:
| > I propose to add a top-level declaration on the form: | > | > 'deriving' qtycls 'for' qtycon | > | > which produces the same instance as a deriving clause in the | > declaration of the datatype or newtype would. | | If this is added (whatever the syntax), you'd also want to permit multiple | identical derived instances.
Perhaps so. This might generate duplicate code (one for each decl) but it'd be guaranteed identical since it's generated by a deriving clause.
It'd require some .hi file support, to record that an instance came from a 'deriving' decl.
I'm inclined to wait until someone asks for it "for real" as it were.
I was actually going to request this, but thought it might not play nice with separate compilation that well. but if the ghc folks don't think it is too much trouble, I would really like that feature. I believe you can output some linker pragmas to have the duplicate bodies merged into one so you won't end up with excess code in your executable.. but would have to look it up to be sure. John -- John Meacham - ⑆repetae.net⑆john⑈
participants (9)
-
Bjorn Bringert
-
Björn Bringert
-
Iavor Diatchki
-
John Meacham
-
Ketil Malde
-
Manuel M T Chakravarty
-
Ross Paterson
-
Simon Peyton-Jones
-
Twan van Laarhoven