
On Tue, Feb 25, 2014 at 11:12 AM, Herbert Valerio Riedel
On 2014-02-25 at 07:44:45 +0100, Michael Snoyman wrote:
[...]
* I know that back in the base 3/4 transition there was good reason for upper bounds on base. Today, it makes almost no sense: it simply prevents cabal from even *trying* to perform a compilation. Same goes with libraries like array and template-haskell, which make up most of the issue with testing of GHC 7.8 Stackage builds[3]. Can any PVP proponent explain why these upper bounds still help us on corelibs?
I assume by 'corelibs' you mean the set of non-upgradeble libs, i.e. those tied to the compiler version? (E.g. `bytestring` would be upgradeable, as opposed to `base` or `template-haskell`)
Yes, that's what I meant. I realize now corelibs wasn't the right term, but I don't think we *have* a correct term for this. I like your usage of upgradeable.
Well, `base` (together with the other few non-upgradeable libs) is indeed a special case; also, in `base` usually care is taken to avoid semantic changes (not visible at the type-signature level), so an upper bound doesn't gain that much in terms of protecting against semantic breakages.
Otoh, the situation changes if you have a library where you have different versions, which are tied to different version ranges of base, where you want Cabal to select the matching version. Admittedly, this is a special case for when use of MIN_VERSION_base() wouldn't suffice, but I wanted to give an example exploiting upper-bounds on the `base` lib.
That situation is technically possible, but highly unlikely to ever occur in practice. Consider what would have to happen: foo-1 is released, which works with base 4.5 and 4.6. It has a version bound base >= 4.5 && < 4.7. foo-2 is released, which only works with base 4.5. It changes its version bound to base >= 4.5 && < 4.6. In other words, a later release of the package would have to drop support for newer GHCs. The far more likely scenario to occur is where foo-1 simply didn't include upper bounds, and foo-2 adds them in. In that case, cabal will try to use foo-1, even though it won't anyway. Does anyone have an actual example of base or template-haskell upper bounds that provided benefit?
There's one other possible minor benefit I can think of, that upper bounds give over compile-errors, which is a more user-friendly message, to point to the reason of the failure, instead of requiring you guess what the actual cause of the compile-error was. But for non-upgradeable packages such as `base`, which do big major version jumps for almost every release (mostly due to changes in GHC modules exposing internals or adding type-class instances[1]), erring on the confusing-compile-error side seems to provide more value.
I'd actually argue that this is a disadvantage. It's true that we want users to have a good experience, but the *best* experience would be to let upstream packages get fixed. Imagine a common build error caused by the removal of `catch` from Prelude in base 4.6. With upper bounds, a user gets the error message "doesn't work with base 4.6" and reports to the package maintainer. The package maintainer then needs to download GHC and try to compile his package before getting any idea what the problem is (if there even *is* a problem!). With more verbose errors, a user could give a meaningful error message and, in many cases, a maintainer would be able to fix the problem without even needing to download a new version of the compiler.
So, as for `base` I mostly agree, that there seems to be little benefit for upper bounds, *unless* a base3/4 situation comes up again in the future. So, I'd suggest (for those who don't want to follow PVP with `base`) to keep using at least a "super"-major upper bound, such as 'base < 5' to leave a door open for such an eventuality.
Cheers, hvr
[1]: I'd argue (but I'd need research this, to back this up with numbers), that we're often suffering from the PVP, because it requires us to perform major-version jumps mostly due to typeclasses, in order to protect against conflicts with possible non-hideable orphan-instances; and that (as some have suggested in past already), we might want to reconsider requiring only a minor bump on instance-additions, and discourage the orphan-instance business by requiring those packages to have tighter-than-major upper-bounds
+1, forcing major version bumps for each new instance just in case someone has an orphan instance is complete overkill. Michael