exchange package:safe-money

Apply the ExchangeRate to the given Dense src monetary value. Identity law:
exchange (exchangeRateRecip x) . exchange x  ==  id
Use the Identity law for reasoning about going back and forth between src and dst in order to manage any leftovers that might not be representable as a Discrete monetary value of src.
Safely construct an ExchangeRate from a *positive* Rational number. If the given Rational is non-positive, returns Nothing.
Unsafely build an ExchageRate monetary value from a Rational value. Contrary to exchangeRate, this function *crashes* if the given Rational a value has zero as a denominator or when it is negative, with the former case being something very unlikely to happen unless the given Rational was itself unsafely constructed. Other than that, exchangeRate and exchangeRate' behave the same. Prefer to use exchangeRate when dealing with Rational inputs from untrusted sources.
denominator x /= 0 && x > 0
⇒ exchangeRate x == Just (exchangeRate' x)
denominator x == 0 || x <= 0
⇒ undefined == exchangeRate' x
Parses a decimal representation of an ExchangeRate.
Reciprocal ExchangeRate. This function retuns the reciprocal or multiplicative inverse of the given ExchangeRate, leading to the following identity law:
exchangeRateRecip . exchangeRateRecip   ==  id
Note: If ExchangeRate had a Fractional instance, then exchangeRateRecip would be the implementation of recip.
Render a ExchangeRate as a decimal number in a potentially lossy manner.
> exchangeRateToDecimal defaultDecimalConf Round
<$> (exchangeRate (123456 % 100) :: Maybe (ExchangeRate "USD" "EUR"))
Just "1,234.56"
Obtain a Rational representation of the ExchangeRate. This Rational is guaranteed to be a positive number.
Exchange rate for converting monetary values of currency src into monetary values of currency dst by multiplying for it. For example, if in order to convert USD to GBP we have to multiply by 1.2345, then we can represent this situaion using:
exchangeRate (12345 % 10000) :: Maybe (ExchangeRate "USD" "GBP")
A monomorphic representation of ExchangeRate that is easier to serialize and deserialize than ExchangeRate in case you don't know the type indexes involved. If you are trying to construct a value of this type from some raw input, then you will need to use the mkSomeExchangeRate function. In order to be able to effectively serialize an SomeExchangeRate value, you need to serialize the following four values (which are the eventual arguments to mkSomeExchangeRate):
Attempt to convert a SomeExchangeRate to a ExchangeRate, provided you know the target src and dst types.
Build a SomeExchangeRate from raw values. This function is intended for deserialization purposes. You need to convert this SomeExchangeRate value to a ExchangeRate value in order to do any arithmetic operation with the exchange rate.
Destination currency name.
Exchange rate. Positive, non-zero.
Source currency name.
Like exchangeRateToDecimal, but takes a SomeExchangeRate as input.
Convert a ExchangeRate to a SomeDiscrete for ease of serialization.
Convert a SomeExchangeRate to a ExchangeRate without knowing the target currency and unit. Notice that src and dst here can't leave its intended scope unless you can prove equality with some other type at the outer scope, but in that case you would be better off using fromSomeExchangeRate directly.