[Haskell-cafe] Platform Versioning Policy: upper bounds are not our friends

wren ng thornton wren at freegeek.org
Fri Aug 24 03:50:17 CEST 2012

On 8/22/12 12:35 PM, David Menendez wrote:
> As I see it, there are four possibilities for a given version of dependency:
> 1. The version DOES work. The author (or some delegate) has compiled
> the package against this version and the resulting code is considered
> good.
> 2. The version SHOULD work. No one has tested against this version,
> but the versioning policy promises not to break anything.
> 3. The version MIGHT NOT work. No one has tested against this version,
> and the versioning policy allows breaking changes.
> 4. The version DOES NOT work. This has been tested and the resulting
> code (if any) is considered not good.
> Obviously, cases 1 and 4 can only apply to previously released
> versions. The PVP requires setting upper bounds in order to
> distinguish cases 2 and 3 for the sake of future compatibility.
> Leaving off upper bounds except when incompatibility is known
> essentially combines cases 2 and 3.


> So there are two failure modes:
> I. A version which DOES work is outside the bounds (that is, in case
> 3). I think eliminating case 3 is too extreme. I like the idea of
> temporarily overriding upper bounds with a command-line option. The
> danger here is that we might actually be in case 4, in which case we
> don't want to override the bounds, but requiring an explicit override
> gives users a chance to determine if a particular version is
> disallowed because it is untested or because it is known to be
> incompatible.

There are two failure modes with overriding stated bounds, however. On 
the one hand, the code could fail to compile. Okay, we know we're in 
case 4; all is well. On the other hand the code could successfully 
compile in ways the package designer knows to be buggy/wrong; we're 
actually in case 4, but the user does not know this. This is why it's 
problematic to simply allow overriding constraints. The package 
developer has some special knowledge that the compiler lacks, but if all 
constraints are considered equal then the developer has no way to convey 
that knowledge to the user (i.e., in an automated machine-checkable 
way). Consequently, the user can end up in a bad place because they 
thought this second failure mode was actually the success mode.

This is why I advocate distinguishing hard constraints from soft 
constraints. By making this distinction, the developer has a means of 
conveying their knowledge to users. A soft bound defines an explicit 
boundary between case 1 and cases 2--4, which can be automatically (per 
PVP) extended to an implicit boundary between cases 1--2 and cases 3--4; 
a boundary which, as you say, can only be truly discovered after the 
code has been published. Extending soft boundaries in this way should be 
safe; at least it's as safe as possible with the foresight available to 
us. On the other hand, a hard bound defines an explicit boundary between 
case 4 and cases 1--3. If these are overridable, things may break 
silently as discussed above--- but the important thing is, in virtue of 
distinguishing hard and soft bounds, the user is made aware of this 
fact. By distinguishing hard and soft bounds, the developer can convey 
their special knowledge to the user. The user can ignore this 
information, but at least they'll do so in an informed way.

Live well,

More information about the Haskell-Cafe mailing list