
So it should have been another family of `Num` classes, within which, various NaN related semantics can be legal, amongst which I'd think:
* Silent propagation of NaN in arithmetics, like `Maybe` monad does, seems quite acceptable * Identity test, namely `NaN` /= `NaN` - this lacks theoretical ground or not? * Comparison, neither `NaN` > 1 nor `NaN` <= 1 - whether or not there's a theoretical framework for this to hold? Maybe `Boolean` type needs enhancement too to do it?
No such family of `Num` classes exists to my aware by now, I just can't help wondering why.
Cheers, Compl
I like to think of NaN as a glimpse of interval arithmetic. NaN is the interval -infintity to infinity [*]. When ordering intervals by reverse inclusion, NaN is indeed the bottom of the domain. For a general (closed) interval [x,y], how would you answer the questions [x,y] < [1,1]? [x,y] /= [1,1]? There are several possibilities known, extending relations on points to relations on sets. See Smyth-, Hoare- and Egli-Milner lifting of relations. So a more descriptive type of Float-ordering may be (<) :: Float -> Float -> RelationLifting -> Bool For example, NaN /= NaN under all three relation liftings mentioned above, but also NaN == NaN, so a /= b = not (a == b) does not hold anymore.
If we take this into consideration, we notice that most interesting computations occur on collections of values, and thus yield a collection of results, not just a single output.
Indeed, one route to real arithmetic is via limits of collections of approximants. For example, consider a dense set of rationals, excluding zero, where that all arithmetic operations are well-defined and total on the approximants. Then express a real number as (Dedekind-)cuts and see what cut operations like 0/0 result in. Each non-proper cut corresponds to a special Float value. Incidentally, this is how Conway constructed his surreal numbers that also contain values like infinity and -0. I'm in favour that there be two floating-point types: One IEEE- compliant that behaves just like in other languages, and one more lawful one (thereby with fewer class instances) that leverages the expressive power of Haskell. Ho matter how broken, the former should be the default unless we want to alienate numerically inclined Haskell adopters. Olaf [*] The mathematical function \(x,y) -> x/y attains every real value arbitrarily close to (0,0), whence NaN = 0/0 should be interpreted as the interval encompassing the real line. Likewise log(0) for complex 0.