Should the PVP be changed with regards to instances?

Hi, I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons: * Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned). Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble! Thoughts? Cheers, Johan

On Tue, Dec 20, 2011 at 6:12 PM, Johan Tibell
Hi,
I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons:
* Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned).
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
Thoughts?
Cheers, Johan
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
+1. New instances will only break code that wrote orphan instances. And I think people who write orphan instances know that this kind of breakage may happen at some point. Michael

On Tue, Dec 20, 2011 at 04:12:32PM +0000, Johan Tibell wrote:
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
I don't like orphan instances either, but users often do define instances they perceive as missing.

Their code breaking is punishment for creating an orphan instance
instead of sending a patch upstream ;)
In theory.. practically speaking that is not always practical to wait
for an upstream maintainer to maybe take your patch to add new
instances.
I have never bumped the major version number just because I added a
new instance. So, I guess I am in favor of making the bump a
'suggests' instead of 'requires'.
When I bump the major version on something like happstack-server. I
then have to update half a dozen other packages to reflect the new
version number. And I have to email maintainers of packages like
digestive-functors, gitit, etc and tell them to bump their version
numbers. Additionally, people packaging happstack for a linux
distribution now have to also update a bunch of packages instead of
just happstack-server. So, that is a lot of work for myself and
others, in the off chance that somebody created an orphan instance.
In theory, bumping the major version sounds like the right thing to
do. But pragmatically.. it is a bit of a burden sometimes. Especially
when compared to the risk of something actually going wrong.
- jeremy
On Tue, Dec 20, 2011 at 10:32 AM, Ross Paterson
On Tue, Dec 20, 2011 at 04:12:32PM +0000, Johan Tibell wrote:
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
I don't like orphan instances either, but users often do define instances they perceive as missing.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 20/12/2011 16:12, Johan Tibell wrote:
I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons:
* Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned).
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
Thoughts?
I'd argue against this: users who write orphan instances typically have no choice, even if they know it's problematic. Contrast this to the fact that we do allow new exports, because a cautious user of the package can avoid problems by explicitly listing what they import. Major version bumps are indeed expensive, but IMO we should address the problem at source by to making them cheaper - e.g. with automated testing/reporting. Ganesh

On Tue, 20 Dec 2011, Ganesh Sittampalam wrote:
I'd argue against this: users who write orphan instances typically have no choice, even if they know it's problematic. Contrast this to the fact that we do allow new exports, because a cautious user of the package can avoid problems by explicitly listing what they import.
The clean solution for orphan instances are separate modules that are approved by the maintainers of the concerned class and type. If the instance can be easily added to the package of the class or the package of the type, then it should be added there.

On 20/12/2011 17:51, Henning Thielemann wrote:
On Tue, 20 Dec 2011, Ganesh Sittampalam wrote:
I'd argue against this: users who write orphan instances typically have no choice, even if they know it's problematic. Contrast this to the fact that we do allow new exports, because a cautious user of the package can avoid problems by explicitly listing what they import.
The clean solution for orphan instances are separate modules that are approved by the maintainers of the concerned class and type. If the instance can be easily added to the package of the class or the package of the type, then it should be added there.
Agreed, but the situation here is that the no pre-approved solution already exists and the author of something that wants those instances has to decide what to do right away. Ganesh

On Tue, 20 Dec 2011, Ganesh Sittampalam wrote:
Agreed, but the situation here is that the no pre-approved solution already exists and the author of something that wants those instances has to decide what to do right away.
The package that provides the orphan instance should define the orphan instance depending on the version of imported packages for the affected class and type. The packages that import the orphan instance package should not need to do such distinctions.

On 21 December 2011 03:55, Ganesh Sittampalam
On 20/12/2011 16:12, Johan Tibell wrote:
I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons:
* Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned).
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
Thoughts?
I'd argue against this: users who write orphan instances typically have no choice, even if they know it's problematic. Contrast this to the fact that we do allow new exports, because a cautious user of the package can avoid problems by explicitly listing what they import.
Major version bumps are indeed expensive, but IMO we should address the problem at source by to making them cheaper - e.g. with automated testing/reporting.
Agreed. (i.e. -1 to the proposal) -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com

On Tue, 20 Dec 2011, Johan Tibell wrote:
Hi, I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons:
* Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned).
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
For the same reason I break the PVP in this respect frequently ... I think that it should be allowed to add instances within a minor version.

I'd ask you to follow the PVP here. Problems with duplicate instances
are often tricky to resolve, and not something you want to encounter
when you're developing (not upgrading dependencies). I've often added
orphan instances for types from other packages. Yes, I should (and
often do) send these upstream, but I still add them locally. I have to
have the instance now, to continue my work, and there's no telling
when a new version of the original package will be released. The other
option is forking the package, which means I also don't get bugfix
updates anymore.
So in short: I find breakage due to conflicting instances much more
annoying than a major version bump.
Erik
On Tue, Dec 20, 2011 at 17:12, Johan Tibell
Hi,
I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons:
* Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned).
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
Thoughts?
Cheers, Johan
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Tue, 20 Dec 2011, Erik Hesselink wrote:
I'd ask you to follow the PVP here. Problems with duplicate instances are often tricky to resolve, and not something you want to encounter when you're developing (not upgrading dependencies). I've often added orphan instances for types from other packages. Yes, I should (and often do) send these upstream, but I still add them locally. I have to have the instance now, to continue my work, and there's no telling when a new version of the original package will be released. The other option is forking the package, which means I also don't get bugfix updates anymore.
A better option is using a newtype and add the missing instances there.

On Tue, Dec 20, 2011 at 19:26, Henning Thielemann
On Tue, 20 Dec 2011, Erik Hesselink wrote:
I'd ask you to follow the PVP here. Problems with duplicate instances are often tricky to resolve, and not something you want to encounter when you're developing (not upgrading dependencies). I've often added orphan instances for types from other packages. Yes, I should (and often do) send these upstream, but I still add them locally. I have to have the instance now, to continue my work, and there's no telling when a new version of the original package will be released. The other option is forking the package, which means I also don't get bugfix updates anymore.
A better option is using a newtype and add the missing instances there.
That is indeed a good option, although newtypes can sometimes be verbose to use. But I'll consider the option next time I run into a missing instance. Thanks, Erik

On 12/20/11 1:24 PM, Erik Hesselink wrote:
I'd ask you to follow the PVP here. Problems with duplicate instances are often tricky to resolve, and not something you want to encounter when you're developing (not upgrading dependencies). I've often added orphan instances for types from other packages. Yes, I should (and often do) send these upstream, but I still add them locally. I have to have the instance now, to continue my work, and there's no telling when a new version of the original package will be released. The other option is forking the package, which means I also don't get bugfix updates anymore.
So in short: I find breakage due to conflicting instances much more annoying than a major version bump.
Agreed with this. And with Ganesh Sittampalam: the solution to the problem of major version changes is automated testing/reporting, not allowing potentially breaking changes in minor versions. Yes orphans are bad, but they can be required as an interim measure (or, with CPP, for backwards compatibility). -- Live well, ~wren

On Wed, Dec 21, 2011 at 11:24 AM, wren ng thornton
Agreed with this. And with Ganesh Sittampalam: the solution to the problem of major version changes is automated testing/reporting, not allowing potentially breaking changes in minor versions.
Can you explain how this helps ? The problem I have is that the chances of adding a new instance breaking something is often pretty low -- possibly 0. But, bumping the major version number requires myself and others to do a bunch of work. Would this automated testing allow me to be sure that nothing will break when I add an instance, and therefore allow me to only bump the minor version number? Obviously, the only way to know is to look in every package the depends on my library and see if it adds any conflicting instances. Though in practice, we can really only check the packages on hackage. Let's say the authors of text add a new instance[1]. I can not actually update to that new version of text until all the other libraries I use that depend on it are updated. For a very popular library, like text, than can take awhile. So, I am stuck with the old version until everybody updates -- and probably all they are going to do is bump the version range. Let's say that there turns out there is a conflict -- some package does create a duplicate instance. Well, I can always use the constraints flag to stick with the older text library until that *one* problem package is updated. Annoying -- yes, but so is the alternative. So, the 'automated' solution I would like to see is one where the text authors upload a new version with a bumped major version, and then something automated happens and I can install text plus all the other libraries that use it with out having to wait for the authors to update their libraries. Alternatively, a system where libraries exported some sort of declaration of the API they need, so that the PVP is irrelevant would be nice too -- if such a thing could be made to work. The core issue is, after all, that we basically have a single bit of information that we use to declare that the API is changed. That is obviously not very fine grained... - jeremy [1] I don't text actually declares any type classes -- but let's pretend it did.

Jeremy Shaw wrote:
On Wed, Dec 21, 2011 at 11:24 AM, wren ng thornton
wrote: Agreed with this. And with Ganesh Sittampalam: the solution to the problem of major version changes is automated testing/reporting, not allowing potentially breaking changes in minor versions.
[--snip--]
Let's say the authors of text add a new instance[1]. I can not actually update to that new version of text until all the other libraries I use that depend on it are updated. For a very popular library, like text, than can take awhile. So, I am stuck with the old version until everybody updates -- and probably all they are going to do is bump the version range.
One of the major problems here, I find, is the fact that packages that your package depends on *but which are not part of the API to your package exposes to the world* lead to conflicts. (I this solvable currently? Perhaps one can create both an *-api package and a *-impl package?) [--snip--]
Alternatively, a system where libraries exported some sort of declaration of the API they need, so that the PVP is irrelevant would be nice too -- if such a thing could be made to work. The core issue is, after all, that we basically have a single bit of information that we use to declare that the API is changed. That is obviously not very fine grained...
Separation of what the package API actually *is* versus what it uses internally would be extremely desirable. I usually find that it's actually "implementation" dependencies that get me into trouble with dependency management. I realize that it may not exactly be a trivial proposition to implement something like this, but AFAICT .cabal files actually contain enough information to (theoretically at least) be able to implement this.

On Tue, Dec 20, 2011 at 2:12 PM, Johan Tibell
I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP.
Stick them on the source repository and wait for some more changes to pile up? Cheers, -- Felipe.

On Tue, Dec 20, 2011 at 11:12 AM, Johan Tibell
Hi,
I find myself reluctant to add new instances to the unordered-containers package, because doing so would require a major version bump according to the PVP. Major version bumps are annoying for several reasons:
* Libraries that depend on unordered-containers need to be updated and make new releases. * We get rapid successions of major releases without many actual changes (i.e. none as far as most users are concerned).
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
I encourage the following of the PVP with new class instances, but I don't always do it myself - I think reasonable people can disagree on this.
Thoughts?
Cheers, Johan
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Hello Johan, On Tue, 2011-12-20 at 08:12 -0800, Johan Tibell wrote:
Introducing new instances is unlikely to break users, as they will only get into trouble if they use orphan instances, which is already asking for trouble!
Thoughts?
just a thought: what about using a more fine-grained versioning scheme, introducing a granularity somewhat in-between the current "major" and "minor" version components: *) X.Y.Z with X,Y and Z denoting major, minor and micro version components *) the new major component X gets incremented on major changes (= old major increments, except for typeclass-instance additions) *) the new minor component Y gets incremented on typeclass-instance additions *) the new micro component Z gets incremented when the old minor component would have been incremented this way, the client code can declare on a dependency, whether new typeclass instances would pose a potential break (e.g. if the client code doesn't define any orphan instances, then the "Y" component increment should pose no threat) -- hvr
participants (13)
-
Antoine Latter
-
Bardur Arantsson
-
Erik Hesselink
-
Felipe Almeida Lessa
-
Ganesh Sittampalam
-
Henning Thielemann
-
Herbert Valerio Riedel
-
Ivan Lazar Miljenovic
-
Jeremy Shaw
-
Johan Tibell
-
Michael Snoyman
-
Ross Paterson
-
wren ng thornton