As a Haskell (GHC platform) beginner I bumped into a problem of dealing with data types and arithmetic operations related to business domain that involves currency/money operations and I'm looking for a solution.
I'm developing application that is supposed to interface with (independent) accounting module (via web services) while at the same time having a (web) user interface for ad-hoc data entry which is stored in a separate database (PostgreSQL).
I'm coming from C#/F# environment and System.Decimal covers all the core needs there. Please correct me if I'm wrong but Haskell does not seem to have an integrated (default) data type that could be considered equivalent.
Ideal choice would be a data type that offers arbitrary precision arithmetic or at least something in the lines of Decimal128 (IEEE 754). The type should support rounding (to nearest, ties away from zero and if possible also ties to even) and the following operations: add, subtract, multiply, divide (ideally also square/root). Conversions between types should also be supported.
From what I've managed to find there are two Haskell modules on Hackage that are supposed to perform calculations exactly - Data.Fixed and Data.Decimal (by the way is there any way of creating custom literals in Haskell - e.g. to copy 123.45m from F# ?). At least the latter would as far as I can tell (after a quick test) enables most of what I've described in previous paragraph, but when I add a DB (PostgreSQL via Persistent/HDBC) and a web framework (YESOD) to the mix things don't look so peachy. The support there seems to be lacking.
Is there any other combination that enables what I've described end-to-end (data entry => data processing => storage) with minimal friction (e.g. manual casting from string after loading from DB seems odd having a really strongly typed language) and without the loss of precision (any pointers welcome)?
123.45
stands forfromRational (2469 % 20)
and whichfromRational
is called is determined by the type. The type is determined by the context (possibly a type signature). SinceRational
exactly handles rational numbers (within the memory limits imposed by the machine resp. GMP), there's no need for typed literals. – Tunicle123.45
. The conversion to a rational and then to a value of the required type is done by the implementation. You don't need to bother with that. The only thing a literal of the form123.45m
would add is that the human reader of the code immediately can see the type - if (s)he knows the meaning of the suffix. – Tuniclelet a = 0.1 + 0.2 + 0.03
- doesn't further references toa
mean using value0.33000000000000007
? – ParentalRational
, not ofDouble
. – Tuniclelet a = ...
above defines a polymorphic value, but only concrete types can actually be evaluated. If nothing constrains the type of such an expression, it will indeed default toDouble
. Haskell has no implicit conversion between numeric types whatsoever, so a single concrete type will disambiguate every calculation it touches, even indirectly. Thus, the GHCi prompt is often the only place you'll ever see type defaulting occur. – Tusk