<div dir="auto">So we have two things here:</div><div dir="auto"><br></div><div dir="auto">* lossy computation that needs  a distance (metric) between points below epsilon instead of a comparison; in this case we should never ask for exact equality, but rather ask if a result is within a certain radius from a result. That means we measure convergence according to a metric, not equivalence.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">```</div><div dir="auto">class Ord m => Metric m a where</div><div dir="auto">   dist :: a -> a -> m</div><div dir="auto"> </div><div dir="auto">a ~= b = dist a b <= epsilon</div><div dir="auto">```</div><div dir="auto"><br></div><div dir="auto">* handling and propagation of different error values.</div><div dir="auto"><br></div><div dir="auto">That would require a rehash of both standard libraries and most mathematical algebra libraries for Haskell.</div><div dir="auto"><br></div><div dir="auto">For at least two reasons:</div><div dir="auto"><br></div><div dir="auto">* libraries assume a naive equality works for all types. Holds in a world of infinte precision and lossless operations, but never holds for approximations.</div><div dir="auto"><br></div><div dir="auto">* our propagation of universal error values is incomplete, and usually missing from complex algorithms. In other words `Either String` Monad does not work: we want collections of error values just like we have collections of inputs.</div><div dir="auto"><br></div><div dir="auto">Personally I will be overjoyed when our community finally gets the better type class library for approximated types.</div><div dir="auto"><br></div><div dir="auto">Would You agree to review a teaser if I post it here?</div><div dir="auto">—</div><div dir="auto">  Cheers</div><div dir="auto">    Michał</div><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 5 Aug 2021 at 10:41 YueCompl <<a href="mailto:compl.yue@icloud.com">compl.yue@icloud.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> 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>
Yeah, I think this is the thing I'm anticipating, current standard classes favor lossless computation by the laws, but large portion of the computer numeric solutions are taking loss of precision for efficiency. And neural systems even right following this approach as far as it appears, I sincerely hope Haskell can embrace it to some degree.<br>
<br>
<br>
> On 2021-08-05, at 15:26, Richard O'Keefe <<a href="mailto:raoknz@gmail.com" target="_blank">raoknz@gmail.com</a>> wrote:<br>
> <br>
> 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>
</blockquote></div></div>-- <br><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">  Pozdrawiam<br>    Michał</div>