Avoiding bumping the major version of base in every release

Hi! Bumping the major version number of base creates a bunch of work for package maintainers. Some times this work is justified, when there were actual non-backwards compatible API changes and maintainers need to fix their code. Often the work is busy work, as there were no real breakages and maintainers need to update their version bounds and make a new release. When bumps to the major version leads to busy work, maintainers often express a desire to get rid of version bounds altogether. While that might be a natural reaction, I don't think that's actually a good idea and it will lead to more breakages in the end*. All this is to say, we should try to avoid major version bumps to base. Here's my suggestion *Short term* - Make sure we only bump the major version number when we actually make a breaking change. We don't need to bump base because the major GHC version number changed. - Try harder to not make breaking changes. Breaking changes has a very high cost to users and are seldom worth it to them. For example, avoid renaming functions just because the new name feels cleaner. Just add a new function and have the old function call the new function. All successful languages do this. *Medium term* - Break up base a bit. There are several other good reasons to do this, but having a monolithic base means that breaking changes to the most obscure modules cause a major version bump for the package as a whole. * But in the case of missing upper bounds, the breakages and extra work falls on the users of libraries, not on their maintainers. That's really bad as the users are not really in a position to deal with the breakages. -- Johan

I just noticed that 7.8.1 bumps the major version of base, but I can't see
any breaking changes in the release notes:
http://www.haskell.org/ghc/docs/7.8.1-rc2/html/users_guide/release-7-8-1.htm...
On Wed, Apr 9, 2014 at 12:00 PM, Johan Tibell
Hi!
Bumping the major version number of base creates a bunch of work for package maintainers. Some times this work is justified, when there were actual non-backwards compatible API changes and maintainers need to fix their code. Often the work is busy work, as there were no real breakages and maintainers need to update their version bounds and make a new release.
When bumps to the major version leads to busy work, maintainers often express a desire to get rid of version bounds altogether. While that might be a natural reaction, I don't think that's actually a good idea and it will lead to more breakages in the end*.
All this is to say, we should try to avoid major version bumps to base. Here's my suggestion
*Short term*
- Make sure we only bump the major version number when we actually make a breaking change. We don't need to bump base because the major GHC version number changed. - Try harder to not make breaking changes. Breaking changes has a very high cost to users and are seldom worth it to them. For example, avoid renaming functions just because the new name feels cleaner. Just add a new function and have the old function call the new function. All successful languages do this.
*Medium term*
- Break up base a bit. There are several other good reasons to do this, but having a monolithic base means that breaking changes to the most obscure modules cause a major version bump for the package as a whole.
* But in the case of missing upper bounds, the breakages and extra work falls on the users of libraries, not on their maintainers. That's really bad as the users are not really in a position to deal with the breakages.
-- Johan

On 2014-04-09 at 12:00:36 +0200, Johan Tibell wrote: [...]
All this is to say, we should try to avoid major version bumps to base. Here's my suggestion
*Short term*
- Make sure we only bump the major version number when we actually make a breaking change. We don't need to bump base because the major GHC version number changed.
Fwiw, I did go over the changes in base-4.7.0.0 when I compiled the changelog to check whether the major bump was justified; but since a couple of deprecated functions where removed, several new typeclass instances were added (however, this isn't a justification anymore), the rather disruptive Typeable change occured, as well as the PrimBool changes (which may leak into the API exposed by base) I believed it was well justified.
- Try harder to not make breaking changes. Breaking changes has a very high cost to users and are seldom worth it to them. For example, avoid renaming functions just because the new name feels cleaner. Just add a new function and have the old function call the new function. All successful languages do this.
Aren't we already following this practice in base?
*Medium term*
- Break up base a bit. There are several other good reasons to do this, but having a monolithic base means that breaking changes to the most obscure modules cause a major version bump for the package as a whole.
* But in the case of missing upper bounds, the breakages and extra work falls on the users of libraries, not on their maintainers. That's really bad as the users are not really in a position to deal with the breakages.

On Wed, Apr 9, 2014 at 2:17 PM, Herbert Valerio Riedel
On 2014-04-09 at 12:00:36 +0200, Johan Tibell wrote:
*Short term*
- Make sure we only bump the major version number when we actually make a breaking change. We don't need to bump base because the major GHC version number changed.
Fwiw, I did go over the changes in base-4.7.0.0 when I compiled the changelog to check whether the major bump was justified; but since a couple of deprecated functions where removed, several new typeclass instances were added (however, this isn't a justification anymore), the rather disruptive Typeable change occured, as well as the PrimBool changes (which may leak into the API exposed by base) I believed it was well justified.
I wasn't aware there was a more detailed changelog. Thanks for pointing it out. I just wanted to make sure we're all on the same page here.
- Try harder to not make breaking changes. Breaking changes has a very high cost to users and are seldom worth it to them. For example, avoid renaming functions just because the new name feels cleaner. Just add a new function and have the old function call the new function. All successful languages do this.
Aren't we already following this practice in base?
I am and I'm hoping others are too. Since hope is not a strategy I just thought I'd spell it out to make sure we all agree. -- Johan

On 2014-04-09 at 14:51:48 +0200, Johan Tibell wrote: [...]
Fwiw, I did go over the changes in base-4.7.0.0 when I compiled the changelog to check whether the major bump was justified; but since a couple of deprecated functions where removed, several new typeclass instances were added (however, this isn't a justification anymore), the rather disruptive Typeable change occured, as well as the PrimBool changes (which may leak into the API exposed by base) I believed it was well justified.
I wasn't aware there was a more detailed changelog. Thanks for pointing it out. I just wanted to make sure we're all on the same page here.
Oh, and btw, here's also a somewhat older API delta (which is only as accurate as the hoogle txt files generated -- i.e. take it with a grain of salt) I generated some time ago: https://gist.github.com/hvr/6648575

Sounds reasonable to me, but I'm fwding this to the Core Libraries committee, who are in charge of all this. On the question of breaking up 'base', see https://ghc.haskell.org/trac/ghc/wiki/SplitBase, which seems stalled for lack of anyone willing to take up the cudgels. Simon From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Johan Tibell Sent: 09 April 2014 11:01 To: ghc-devs@haskell.org Subject: Avoiding bumping the major version of base in every release Hi! Bumping the major version number of base creates a bunch of work for package maintainers. Some times this work is justified, when there were actual non-backwards compatible API changes and maintainers need to fix their code. Often the work is busy work, as there were no real breakages and maintainers need to update their version bounds and make a new release. When bumps to the major version leads to busy work, maintainers often express a desire to get rid of version bounds altogether. While that might be a natural reaction, I don't think that's actually a good idea and it will lead to more breakages in the end*. All this is to say, we should try to avoid major version bumps to base. Here's my suggestion Short term * Make sure we only bump the major version number when we actually make a breaking change. We don't need to bump base because the major GHC version number changed. * Try harder to not make breaking changes. Breaking changes has a very high cost to users and are seldom worth it to them. For example, avoid renaming functions just because the new name feels cleaner. Just add a new function and have the old function call the new function. All successful languages do this. Medium term * Break up base a bit. There are several other good reasons to do this, but having a monolithic base means that breaking changes to the most obscure modules cause a major version bump for the package as a whole. * But in the case of missing upper bounds, the breakages and extra work falls on the users of libraries, not on their maintainers. That's really bad as the users are not really in a position to deal with the breakages. -- Johan

The current plan with breaking up base is mostly to push it out until we
get the lower hanging fruit out of the way for 7.10, and to start moving
forward more aggressively on that around 7.12.
Back at ICFP we made the call to more or less take greater ownership of
base upon the release of 7.8. Given the release timeline that was perhaps,
in hindsight, a mistake, as it drained a lot of momentum.
That said, now that 7.8 is out the door we can at least get started on the
Foldable/Traversable/Applicative/Monoid changes and AMP.
The orginal plan, and one that I think is still a good plan going forward,
is that the changes for 7.10 should be done in such a way that most users
can work around them all without CPP at all, and just enjoy the greater
flexibility of Foldable/Traversable/Applicative/Monoid in Prelude. I think
the major things broken by those inclusions are <> and <$> in the pretty
printing libraries, which could hide two symbols, and a boatload of
redundant import warnings.
Almost any serious stab at breaking up base to meet the demands of the
javascript crowd, one of the two major reasons for breaking up base, is
going to cause some serious challenges for the very makeup of the Prelude
we export today. I'm all for doing splitting up base, but it is definitely
stalled for a reason, and I think that given the scope of work in just
modernizing the Prelude, we've got a lot bitten off already for this coming
year in 7.10.
Beyond that, one potentially viable plan is to break it up in phases -- if
the more invasive changes needed to make the ghcjs/haste crowd can't
converge for 7.12 we could at least start splintering off some parts of
base that don't feed into the Prelude. That would let us better meet
Johan's goal of an eventually more stable base version number as those
things at the fringes of base are the kinds of thing that iterate quickly,
but very little of the Prelude itself changes from release to release --
although, 7.10 will be a rather large exception in that regard.
-Edward
On Wed, Apr 9, 2014 at 4:50 PM, Simon Peyton Jones
Sounds reasonable to me, but I’m fwding this to the Core Libraries committee, who are in charge of all this.
On the question of breaking up ‘base’, see https://ghc.haskell.org/trac/ghc/wiki/SplitBase, which seems stalled for lack of anyone willing to take up the cudgels.
Simon
*From:* ghc-devs [mailto:ghc-devs-bounces@haskell.org] *On Behalf Of *Johan Tibell *Sent:* 09 April 2014 11:01 *To:* ghc-devs@haskell.org *Subject:* Avoiding bumping the major version of base in every release
Hi!
Bumping the major version number of base creates a bunch of work for package maintainers. Some times this work is justified, when there were actual non-backwards compatible API changes and maintainers need to fix their code. Often the work is busy work, as there were no real breakages and maintainers need to update their version bounds and make a new release.
When bumps to the major version leads to busy work, maintainers often express a desire to get rid of version bounds altogether. While that might be a natural reaction, I don't think that's actually a good idea and it will lead to more breakages in the end*.
All this is to say, we should try to avoid major version bumps to base. Here's my suggestion
*Short term*
- Make sure we only bump the major version number when we actually make a breaking change. We don't need to bump base because the major GHC version number changed. - Try harder to not make breaking changes. Breaking changes has a very high cost to users and are seldom worth it to them. For example, avoid renaming functions just because the new name feels cleaner. Just add a new function and have the old function call the new function. All successful languages do this.
*Medium term*
- Break up base a bit. There are several other good reasons to do this, but having a monolithic base means that breaking changes to the most obscure modules cause a major version bump for the package as a whole.
* But in the case of missing upper bounds, the breakages and extra work falls on the users of libraries, not on their maintainers. That's really bad as the users are not really in a position to deal with the breakages.
-- Johan
-- You received this message because you are subscribed to the Google Groups "haskell-core-libraries" group. To unsubscribe from this group and stop receiving emails from it, send an email to haskell-core-libraries+unsubscribe@googlegroups.com. For more options, visit https://groups.google.com/d/optout.
participants (4)
-
Edward Kmett
-
Herbert Valerio Riedel
-
Johan Tibell
-
Simon Peyton Jones