Haskell Decimal Libraries - Financial App - IEEE 754-2008

I’m looking for libraries for storing and working with currency.

I’ve found a few so far but would be interested in seeing if there are any that I’ve overlooked.
I’ll be doing calculations on these values (variance, square root, standard deviation) so it would be ideal if they had instances for working with standard math operators (+, -, ^, sqrt, log, etc).

Numeric.Decimal

It has support for IEEE 754-2008 but is marked as experimental.

Data.Decimal

Works with arithmetic operators but missing instance for Fractional so I can’t use it with sqrt and friends without implementing the functionality myself it seems. Despite this, it looks promising.

Data.Ratio
http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Ratio.html

Has a tendency to explode in space and performance can be poor.

Data.Scientific
http://hackage.haskell.org/package/scientific-0.3.3.5/docs/Data-Scientific.html

Looks good, but from the documentation: Although Scientific is an instance of Fractional , the methods are only partially defined! Specifically recip and / will diverge (i.e. loop and consume all space) when their outputs have an infinite decimal expansion

2 Likes

I would say as soon as you do a sqrt, you aren’t dealing with currency anymore, right? Now you’re doing analysis on currency as if it were a real number, which is probably the time to move to (newtypes over) floats, or some other approximation of the reals.

1 Like

That’s a good perspective, and I like it. I was hoping for a quick win and would be able to use one accurate type throughout, but I’ll consider the approximation.

Using Data.Decimal I was to get unit tests passing which were failing when using Doubles. The actual and expected result differed by a small amount when using Doubles. I could have tested for a lesser precision rather than for an exact match, but it was nice to see that the calculations could be done so accurately.

This is really the only possibility, if I remember my numerical analysis courses properly. You definitely want integers for counting your currency, but lots of useful analysis introduces both rounding errors and estimation errors. If you aren’t keeping track of those, you’re probably introducing bugs. :slight_smile: And with some known error e, the best equivalence you can test for is the fuzzy |a1 - a2| < e

In the case of calculating the interest to be paid or received, you may need sqrt or other functions that work rather on doubles than on integers. This leads to rounding rules and handling the precision appropriately, but we are still calculating something that will give a currency (not analysis, but actual amounts). There are also other cases e.g. in accounting and handling currencies, where you may need doubles.

Or you can use recurring-fractions… those should handle this as well… but computations can get way expensive as you just cache everything in lazy lists & only do the computation up to the needed precision in the end.