<div dir="auto">Well said. </div><div dir="auto"><br></div><div dir="auto">I do think signalling nans as a runtime flag option that converts them into exceptions is still a pretty viable option. The right hooks in the rts are there !</div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Aug 5, 2021 at 12:28 AM Richard O'Keefe <<a href="mailto:raoknz@gmail.com">raoknz@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">You quoted<br>
"> Note that due to the presence of @NaN@, not all elements of 'Float'<br>
have an additive inverse."<br>
<br>
Let x y and z be finite floating-point numbers such that x + y ==> z.<br>
Does there always exist neg(y) such that z + neg(y) ==> x?<br>
NO.<br>
<br>
And the presence or absence of NaN in the system makes no difference.<br>
If, for example, you add 1.0e-18 to 1.0e0, the answer is 1.0e0 exactly.<br>
That is, (x + y) - y == 0, but x is not 0.<br>
<br>
In the presence of rounding, additive inverses do not in general exist.<br>
Neither do multiplicative inverses.<br>
<br>
Also addition and multiplication are not associative, but you knew that.<br>
The only reason Float and Double are in Num is because Haskell doesn't<br>
offer ad hoc overloading. People have been saying that the Prelude needs<br>
refactoring for years.<br>
<br>
The main thing that NaN wrecks that wasn't already broken is Eq. I would<br>
argue that the right decision there would have been to rule that x == y<br>
(when x and y are floating point numbers) precisely when x and y are<br>
represented by the same bit pattern, with a separate operation for IEEE<br>
"ordered and equal".<br>
<br>
At some point, Haskell should make provision for decimal floating point,<br>
as the current versions of IEEE 754 and C do, and that might be a good<br>
reorganisation time.<br>
<br>
<br>
On Thu, 5 Aug 2021 at 02:05, YueCompl via Haskell-Cafe<br>
<<a href="mailto:haskell-cafe@haskell.org" target="_blank">haskell-cafe@haskell.org</a>> wrote:<br>
><br>
> Thanks Michał,<br>
><br>
> I feel less confused as I realized the non-halting possibility per bottoms, from your hint.<br>
><br>
> I too think the signaling NaN is dreadful enough, so fortunately it's rarely seen nowadays.<br>
><br>
> Actually what's on my mind was roughly something like "Maybe on steroids", I'm aware that NaN semantics breaks `Num` (or descendants) laws, as seen at <a href="https://gitlab.haskell.org/ghc/ghc/-/blob/master/libraries/base/GHC/Float.hs" rel="noreferrer" target="_blank">https://gitlab.haskell.org/ghc/ghc/-/blob/master/libraries/base/GHC/Float.hs</a><br>
><br>
> > Note that due to the presence of @NaN@, not all elements of 'Float' have an additive inverse.<br>
><br>
> > Also note that due to the presence of -0, Float's 'Num' instance doesn't have an additive identity<br>
><br>
> > Note that due to the presence of @NaN@, not all elements of 'Float' have an multiplicative inverse.<br>
><br>
> So it should have been another family of `Num` classes, within which, various NaN related semantics can be legal, amongst which I'd think:<br>
><br>
> * Silent propagation of NaN in arithmetics, like `Maybe` monad does, seems quite acceptable<br>
> * Identity test, namely `NaN` /= `NaN` - this lacks theoretical ground or not?<br>
> * 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?<br>
><br>
> No such family of `Num` classes exists to my aware by now, I just can't help wondering why.<br>
><br>
> Cheers,<br>
> Compl<br>
><br>
> On 2021-08-04, at 02:38, Michał J Gajda <<a href="mailto:mjgajda@gmail.com" target="_blank">mjgajda@gmail.com</a>> wrote:<br>
><br>
> Dear Yue,<br>
><br>
> Bottom has much weaker semantics than an exception: it means You may never get a result and thus will never handle it!<br>
><br>
> Another reason is convenience: it is frequently the case that giving NaN in a row of numbers is much more informative than crashing a program with an exception and never printing the result anyway.<br>
><br>
> Finally IEEE special values have clear propagation semantics: they are basically Maybe on steroids.<br>
><br>
> The problem with this approach is indeed a silent handling.<br>
><br>
> But in order to fix this, it is better to add preconditions to specific algorithms that do not allow IEEE special value on input (`isFinite` or `isNotNaN`) and then track the origin of the special value with the methods like those described here: <a href="https://skillsmatter.com/skillscasts/14905-agile-functional-data-pipeline-in-haskell-a-case-study-of-multicloud-api-binding" rel="noreferrer" target="_blank">https://skillsmatter.com/skillscasts/14905-agile-functional-data-pipeline-in-haskell-a-case-study-of-multicloud-api-binding</a><br>
><br>
> Never throw an error without telling exactly why it happened and exactly where to fix it :-). Using bottom is last resort; exceptions likewise.<br>
> --<br>
> Cheers<br>
> Michał<br>
><br>
><br>
> _______________________________________________<br>
> Haskell-Cafe mailing list<br>
> To (un)subscribe, modify options or view archives go to:<br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
> Only members subscribed via the mailman list are allowed to post.<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div></div>