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
Validity
instance forDouble
Version 0.4.0.0 until 0.6.0.0 had an instance for
Validity
where-Infinity
,+Infinity
andNaN
are not considered valid.Version 0.7.0.0 had an instance for
Validity
where-Infinity
,+Infinity
,NaN
and-0
are not considered valid.Version 0.8.0.0 had an instance for
Validity
where-Infinity
,+Infinity
andNaN
are not considered valid.Version 0.9.0.0 has an instance for
Validity
where 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
Double
the implementation of the IEEE 754 Double precision floating point standard.Round-trip properties involving
Double
do not hold any more. Indeed, when encodingNaN
and (correctly) decoding it toNaN
again, the result will not equal the starting point becauseNaN == NaN
evaluates toFalse
.Parsers can now be tested with
producesValidsOnValids
in the context ofDouble
where they couldn't be otherwise. Indeed, decoding aNaN
value could be correct.You can still consider a
NaN
invalid if it occurs as part of a custom type.
Consider NaN
invalid
This makes sense if you consider
Double
as a type of rational numbers.This makes sense if you see
NaN
as an unhandled error instead of a value.This hides broken code:
Eq Double
andOrd Double
when testing for valid values, for better or for worse.Would avoid boilerplate if one's own code does not deal with
NaN
values.You can still use
genUnchecked
to test code withNaN
values 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
.