The Validity instance of Double and Float have been the most frequently modified and most controversial part of the validity library. This post announces validity-0.9.0.0 and discusses the changes.
History
The following is a concise summary of the history of Validity Double for reference.
Version 0.1.0.0 until 0.3.0.0 had no
Validityinstance forDoubleVersion 0.4.0.0 until 0.6.0.0 had an instance for
Validitywhere-Infinity,+InfinityandNaNare not considered valid.Version 0.7.0.0 had an instance for
Validitywhere-Infinity,+Infinity,NaNand-0are not considered valid.Version 0.8.0.0 had an instance for
Validitywhere-Infinity,+InfinityandNaNare not considered valid.Version 0.9.0.0 has an instance for
Validitywhere any double is trivially valid.
Controversy
The Validity instance for Double has been highly controversial. The debate centers around whether NaN should be considered a valid value of type Double. The reason that this matters is because Eq Double exist and not such that == is an equivalence relationship. On a related note: Ord Double is similarly broken.
The reasons that led to the decision to consider NaN a valid value are saved in the repository as well, and can be found here.
The main trade-offs are as follows:
Consider NaN valid
This makes sense if you consider
Doublethe implementation of the IEEE 754 Double precision floating point standard.Round-trip properties involving
Doubledo not hold any more. Indeed, when encodingNaNand (correctly) decoding it toNaNagain, the result will not equal the starting point becauseNaN == NaNevaluates toFalse.Parsers can now be tested with
producesValidsOnValidsin the context ofDoublewhere they couldn't be otherwise. Indeed, decoding aNaNvalue could be correct.You can still consider a
NaNinvalid if it occurs as part of a custom type.
Consider NaN invalid
This makes sense if you consider
Doubleas a type of rational numbers.This makes sense if you see
NaNas an unhandled error instead of a value.This hides broken code:
Eq DoubleandOrd Doublewhen testing for valid values, for better or for worse.Would avoid boilerplate if one's own code does not deal with
NaNvalues.You can still use
genUncheckedto test code withNaNvalues if you want.
Breakage
Version 0.9.0.0 is not backward compatible with 0.8.0.0. It will most likely cause failing tests where those tests would not previously fail. In some cases those new failures are previously undiscovered bugs. (In particular, the following bugs were found in hashable, binary and aeson as a result of this change.) In other cases they are false positives that you need not care about. In the case of false positives, you should now add invariants to your data types that specify that the contained Double should not be NaN. Convenience functions have been added to make that easier: validateNotNaN and validateNotInfinite.