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.

Right-o.


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,
~wren

_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to