[Haskell-cafe] Why not some subclass of Floating to model NaNs as some handleable bottom?

Olaf Klinke olf at aatal-apotheke.de
Thu Aug 5 18:48:09 UTC 2021

> 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

> 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


[*] 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.

More information about the Haskell-Cafe mailing list