Closed xnomagichash closed 6 years ago
It was added to support floating literals of type Scientific.
I definitely understand the benefits of that.
The trouble is this: we wrote a function that takes Fractional
in our library code. An engineer working on app-level code passed a Scientific from an Aeson.Number
into the function at the app-level and it type-checked. The engineer had no way of knowing that several layers of abstraction down division was being done.
Instead of raising an error or crashing threads on our server would hang seemingly at random on certain payloads. Debugging this required peeling away layers of abstraction and tracing practically every line of code because a non-termination bug in a multi-threaded application doesn't result in any sort of usable debugging output.
We see no good resolution for this in our code because Aeson uses Scientific so we can't avoid it entirely. The alternative would be to abandon Fractional in our library code and force Double, but we deal with multiple precision in our data so it would be a troubling solution.
I would propose that instead of having non-terminating Fractional
methods in Scientific, one of three solutions should be adopted:
error
on any potentially unsafe method.Double
internally for potentially unsafe operations, sacrificing exactness for guaranteed termination.If any of these is palatable to you we are happy to contribute a patch.
I'm sorry to hear this.
I'm beginning to think it's best to just drop the Fractional instance and provide unsafeFromRational :: Rational -> Scientific
. We would loose floating literals but that's a small price to pay compared to your debugging time.
I just realized that the RealFrac
instance requires a Fractional
instance. So if I drop the Fractional
instance I also have to drop the RealFrac
instance. That won't be nice because I think round
and some other methods of RealFrac
are heavily used.
Maybe it's better to go with your solution 1. For detecting non-termination we can use fromRationalRepetend which detects repeating decimals (which I think is the same as non-termination).
e7461bc7a14a33f95b43406923da8cddb0e4f9f6 should do it.
fromRational
from scientific-0.3.6.1 now throws an error when applied to a repeating decimal.
I realize this is documented, but it appears unsafe to use any method of Fractional with Scientific. What is the rationale for keeping it as an instance of Fractional in that case?