Hey everyone! I’m having trouble with Aeson and Yesod. I’m using them to handle HTTP requests, but I’m running into a problem with large numbers.
I’ve got this setup:
data Cash = EUR Double
$(deriveJSON defaultOptions ''Cash)
-- In my handler
payment <- requireCheckJsonBody :: Handler Cash
The issue is when I send a big number like EUR 9876543210.98, the payment value ends up as 9,876,543,000.0. It’s rounding off the last few digits!
I think it’s because of how it converts from scientific notation to a Double. Does anyone know how to keep the full precision? I really need those cents to be accurate!
I’ve dealt with this exact issue in a financial app I worked on. Using Double for currency is asking for trouble. We switched to the ‘safe-money’ library, which was a game-changer. It’s specifically designed for handling monetary values and integrates well with Aeson.
You’d redefine your Cash type like this:
import Money (Dense, EUR)
data Cash = Cash (Dense "EUR")
Then adjust your JSON instances. It handles serialization beautifully and maintains precision. Plus, it provides type-safe operations for currency manipulation.
It’s a bit more work upfront, but it saved us countless headaches down the line. Trust me, your future self (and your accountants) will thank you for making the switch now.
hey mike, i’ve seen this before. aeson uses scientific notation internally which can cause precision issues with big floats. try using Data.Scientific instead of Double. it’ll keep full precision. you’ll need to tweak your Cash type and JSON instances a bit, but it should solve ur problem. lmk if u need more help!
I’ve encountered this issue in my projects as well. The problem stems from the inherent limitations of floating-point representation in computers. For financial calculations, it’s crucial to maintain precision. I’d recommend using the ‘Data.Decimal’ package instead of ‘Double’. It provides arbitrary-precision decimal arithmetic, which is ideal for monetary values. You’ll need to modify your ‘Cash’ type and adjust the JSON instances accordingly. This approach ensures you retain all significant digits, including those crucial cents. It might require a bit more setup, but it’s worth it for accurate financial computations.