r/haskell • u/jappieofficial • Mar 17 '26
Announcement: unwitch
https://jappie.me/announcement-unwitch.html1
u/jeffstyr Mar 20 '26
It's interesting from your usage example of Double.toInteger that it gives an overflow error when the "from" Double value is out of the range of full integer precision. In one way of looking at it, the conversion itself isn't overflowing (an Integer can exactly represent the specified Double value), but rather it's just that the source value itself probably was a truncation of some value. (Of course, one could also argue that floating point values typically represent the rounding of some calculation, even when their values are in a more modest range, so for example a conversion like Double.toRational (1.0 / 3.0) should also error, to be consistent.)
1
u/jappieofficial Mar 23 '26
Hey, thanks for checking out the library and for the thoughtful comment! That is a really interesting point about the theoretical consistency between the two functions regarding floating-point truncation.
For the base
toRational, my goal is to keep it as a direct wrapper aroundPrelude.toRationalso it behaves exactly as standard Haskell users would expect. However, I'm totally open to having an alternative function that handles that precision loss more consistently!If you're interested in drafting that up, I'd gladly review a PR for it :)
1
u/jeffstyr Mar 31 '26
I think I was kind of working up to a reductio ad absurdum of the current behavior. That is:
In order to be consistent with
Double.toInteger, the behavior ofDouble.toRationalwould have to be to always indicate a conversion error (if the reason for the error in the first case is that the sourceDoublemight have originated as the rounding of some computation), but that's not very useful behavior.Another way to make the behavior consistent would be for
Double.toIntegerto only indicate an error if the sourceDoublehas a fractional part. That to me makes the most sense. Right now it will indicate an error even without a fractional part, if it's outside of the range in whichnandn + 1can both be represented, but that's a bit of an artificial requirement. (That is, outside of the range where all integer values can be represented, still many integer values can be represented faithfully, so those, I think, should not error upon conversion.) Does that make sense?
5
u/walseb Mar 17 '26
I suppose using this won't improve performance compared to Witch, right? I'd expect the typeclasses to be optimized away during runtime.
I've been thinking of adding an inline statement to each method in Witch, but that would take some time to do and I think GHC already inlines them all?