
This does not seem right to me: Prelude Data.Number.Fixed> read "4.00" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.00 Prelude Data.Number.Fixed> read "4.01" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.00 Prelude Data.Number.Fixed> read "4.02" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.03 Prelude Data.Number.Fixed> read "4.03" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.04 Prelude Data.Number.Fixed> read "4.04" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.05 Maybe I am misunderstanding the purpose of this library. I guess that "two digits" of precision means that it is accurate within +/- 0.01? I think that this library is meant for doing arbitrary-precision transcendental operations. But it would not be good as a model for something like currency. It's using ratios as an internal representation, and I'm not sure what ratios it's choosing, but I think I'd choose, say, 401/100 for the "4.01" representation. I guess it's picking a slightly smaller factor than that. The non-reversibility of read/show is somewhat disconcerting. I think I prefer the Decimal library for currency. Regards, Lyle

I prefer the Decimal library for currency.
here is another option to consider: data Cur = Eur | ... data Money = Mint Cur Int | Mtup Cur (Int,Int) precision::Cur -> Int precision Eur = 2 precision _ = 2 € 10.02 would be: Mint Eur 1002 Mtup Eur (10,2) This adds overhead to computations. However precision and correct currency is guaranteed.

Yes, that is similar to what the Decimal library does. It maintains a
precision value and a scaled integer.
So € 10.02 could be represented as:
Decimal 2 1002
It also has nice functions for dividing out currency into equal parts, or
ratios, while preserving the property that the total of the parts should
add up to the original value.
I just thought it might be interesting to encode the precision in the type,
and just use an integer in the representation. Then it's even more
efficient at runtime. Maybe I'll write my own library. Or perhaps there's
another one that does that already.
The Data.Number.Fixed library encodes the precision in the type, but it
uses rational number for the values, and only guarantees the precision
within an epsilon range, so that "two digits of precision" means it could
be +/- .01, which is not good for currency.
On Sat, Mar 5, 2016 at 12:26 AM, Imants Cekusins
I prefer the Decimal library for currency.
here is another option to consider:
data Cur = Eur | ... data Money = Mint Cur Int | Mtup Cur (Int,Int)
precision::Cur -> Int precision Eur = 2 precision _ = 2
€ 10.02 would be: Mint Eur 1002 Mtup Eur (10,2)
This adds overhead to computations. However precision and correct currency is guaranteed.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

Lyle Kopnicky
This does not seem right to me:
Prelude Data.Number.Fixed> read "4.00" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.00 Prelude Data.Number.Fixed> read "4.01" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.00 Prelude Data.Number.Fixed> read "4.02" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.03 Prelude Data.Number.Fixed> read "4.03" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.04 Prelude Data.Number.Fixed> read "4.04" :: Fixed (EpsDiv10 (EpsDiv10 Eps1)) 4.05
Why not just use Data.Fixed from base?
import Data.Fixed read "4.02" :: Fixed E2 4.02
-- - Frank

On Sat, Mar 5, 2016 at 10:37 AM, Frank Staals
Why not just use Data.Fixed from base?
import Data.Fixed read "4.02" :: Fixed E2 4.02
Thanks, I had overlooked that one. That is much more satisfyingly accurate for read/show reversibility. It also has the advantage of encoding the precision in the type. Oddly, it doesn't allow all precisions but just gives you a fixed set of them. Also, It doesn't provide any operations for converting between the precisions, rounding, or divvying out values in proportions without losing pieces of it. And it forces you to stick with Integer as the underlying representation, whereas Decimal lets you choose which sort of Integral to use. It's interesting that Data.Fixed uses a type class to encode the precision. I would have thought using a recursive type like Data.Number.Fixed would make the most sense (each type being defined to have a precision of a factor of 10 more than the preceding one), but now I wonder if there might be some loss of efficiency during conversion due to that. Overall I would go for the Decimal library for currency manipulation. It was clearly designed explicitly for that purpose. The only disadvantages are due to storing the precision in the value: potential inefficiency, and ease of accidentally doing arithmetic on values of two different precisions without explicit coercion. The advantages include being able to choose the underlying integral type, show/read reversibility, and the library operations for divvying up amounts into proportions while guaranteeing that the sum matches the original value. Not that one couldn't write operations to do the divvying, using Data.Fixed. Its constructor is exposed, so one can easily add new operations. Likewise, coercion operations could be added.
participants (3)
-
Frank Staals
-
Imants Cekusins
-
Lyle Kopnicky