elm/core

NaN > NaN and NaN >= NaN do not adhere to IEEE-754

rriegs opened this issue · 1 comments

IEEE-754 requires that all comparisons between NaN and any other number (including NaN) return false (except not-equals, which naturally returns true). Elm, however, returns true for both NaN > NaN and NaN >= NaN.

In addition, Elm's handling of NaN in Basics.compare is questionable. Borrowing from https://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values, clause 5.11, paragraph 2 of the 754-2008 standard:

Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself.

Basics.compare, however, can only return one of LT, EQ, or GT, and ends up returning GT for any combination of inputs involving NaN, e.g. it effectively asserts both 1 > NaN and NaN > 1 in addition to the behavior above. I realize changing the Basics.compare behavior to permit a fourth relation would break quite a lot of code, and leaves unanswered any question as how to, e.g., sort Lists containing NaNs among other Floats. (Right now, where the NaNs end up depends on where they occur in the input list. Further, Dicts and Sets can insert multiple NaNs but cannot find them!)

Accordingly, I respectfully recommend (1) fixing infix operators > and >= to return false for any NaN input and (2), in the interest of supporting NaNs in Dicts, Sets, and List.sort, adjusting Basics.compare to regard NaN as equal to itself and greater than all other input. While this makes Basics.compare behave differently from the infix operators, I note this is already the case, and is more or less necessary without adding a fourth Order value.

This is related to but distinct from #988. Depending on if Basics.compare is implicitly called by == for composite types, addressing (2) may result in such objects consistently comparing equal. However, NaN == NaN should still return false to agree with IEEE-754.