-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Type-safe and lossless encoding and manipulation of money, fiat currencies,
--   crypto currencies and precious metals.
--   
--   Type-safe and lossless encoding and manipulation of money, fiat
--   currencies, crypto currencies and precious metals.
--   
--   NOTICE that the only mandatory dependencies of this package are
--   <tt>base</tt>, <tt>binary</tt>, <tt>constraints</tt>, <tt>deepseq</tt>
--   and <tt>text</tt>. Except for <tt>constraints</tt>, all of them are
--   included with a standard GHC distribution. The rest of the
--   dependencies are OPTIONAL but enabled by default (except
--   <tt>store</tt> which is disabled when building with GHCJS because it
--   doesn't compile ther). All of the optional dependencies can be
--   disabled with Cabal flags.
@package safe-money
@version 0.6


-- | Import this module qualified as follows:
--   
--   <pre>
--   import qualified Money
--   </pre>
--   
--   Note: This module exports many well-known currencies out-of-the-box,
--   but you are not limited to the currencies mentioned here. You can
--   simply create a new <a>Scale</a> instance, and <i>voilà</i>. If you
--   want to add a new currency to the out-of-the-box offer, please request
--   so in <a>https://github.com/k0001/safe-money/issues</a> and the
--   authors will see to it.
--   
--   This module offers plenty of documentation, but for a deep explanation
--   of how all of the pieces fit together, please read
--   <a>https://ren.zone/articles/safe-money</a>. Notice, however, that
--   this library has changed a bit since that article was written. You can
--   always see the <a>change log</a> to understand what has changed.
module Money

-- | <a>Dense</a> represents a dense monetary value for <tt>currency</tt>
--   (usually a ISO-4217 currency code, but not necessarily) as a rational
--   number.
--   
--   While monetary values associated with a particular currency are
--   discrete (e.g., an exact number of coins and bills), you can still
--   treat monetary values as dense while operating on them. For example,
--   the half of <tt>USD 3.41</tt> is <tt>USD 1.705</tt>, which is not an
--   amount that can't be represented as a number of USD cents (the
--   smallest unit that can represent USD amounts). Nevertheless, if you do
--   manage to represent <tt>USD 1.709</tt> somehow, and you eventually
--   multiply <tt>USD 1.705</tt> by <tt>4</tt> for example, then you end up
--   with <tt>USD 6.82</tt>, which is again a value representable as USD
--   cents. In other words, <a>Dense</a> monetary values allow us to
--   perform precise calculations deferring the conversion to a
--   <a>Discrete</a> monetary values as much as posible. Once you are ready
--   to approximate a <a>Dense</a> value to a <a>Discrete</a> value you can
--   use one <a>discreteFromDense</a>. Otherwise, using <a>toRational</a>
--   you can obtain a precise <a>Rational</a> representation.
data Dense (currency :: Symbol)

-- | <a>Dense</a> currency identifier.
--   
--   <pre>
--   &gt; <a>denseCurrency</a> (<a>dense'</a> 4 :: <a>Dense</a> "USD")
--   "USD"
--   </pre>
denseCurrency :: KnownSymbol currency => Dense currency -> Text

-- | Build a <a>Dense</a> monetary value from a <a>Rational</a> value.
--   
--   For example, if you want to represent <tt>USD 12.52316</tt>, then you
--   can use:
--   
--   <pre>
--   <a>dense</a> (125316 <a>%</a> 10000)
--   </pre>
--   
--   Notice that <a>dense</a> returns <a>Nothing</a> in case the given
--   <tt>Rational'</tt>s denominator is zero, which although unlikely, it
--   is possible if the <a>Rational</a> was unsafely constructed. When
--   dealing with hardcoded or trusted <a>Rational</a> values, you can use
--   <a>dense'</a> instead of <a>dense</a> which unsafely constructs a
--   <a>Dense</a>.
dense :: Rational -> Maybe (Dense currency)

-- | Unsafely build a <a>Dense</a> monetary value from a <a>Rational</a>
--   value. Contrary to <a>dense</a>, this function *crashes* if the given
--   <a>Rational</a> has zero as a denominator, which is something very
--   unlikely to happen unless the given <a>Rational</a> was itself
--   unsafely constructed. Other than that, <a>dense</a> and <a>dense'</a>
--   behave the same.
--   
--   Prefer to use <a>dense</a> when dealing with <a>Rational</a> inputs
--   from untrusted sources.
--   
--   <pre>
--   <a>denominator</a> x /= 0
--     ⇒ <a>dense</a> x == <a>Just</a> (<a>dense'</a> x)
--   </pre>
--   
--   <pre>
--   <a>denominator</a> x == 0
--     ⇒ <a>undefined</a> == <a>dense'</a> x
--   </pre>
dense' :: Rational -> Dense currency

-- | Convert currency <a>Discrete</a> monetary value into a <a>Dense</a>
--   monetary value.
denseFromDiscrete :: GoodScale scale => Discrete' currency scale -> Dense currency

-- | Parses a decimal representation of a <a>Dense</a>.
--   
--   Leading <tt>'-'</tt> and <tt>'+'</tt> characters are considered.
denseFromDecimal :: Maybe Char -> Char -> Rational -> Text -> Maybe (Dense currency)

-- | Render a <a>Dense</a> monetary amount as a decimal number in a
--   potentially lossy manner.
--   
--   <pre>
--   &gt; <a>denseToDecimal</a> <a>Round</a> <a>True</a> (<a>Just</a> ',') '.' 2 (1 <a>%</a> 1)
--        (<a>dense'</a> (123456 <a>%</a> 100) :: <a>Dense</a> "USD")
--   Just "+1,234.56"
--   </pre>
--   
--   <pre>
--   &gt; <a>denseToDecimal</a> <a>Round</a> <a>True</a> (<a>Just</a> ',') '.' 2 (100 <a>%</a> 1)
--        (<a>dense'</a> (123456 <a>%</a> 100) :: <a>Dense</a> "USD")
--   Just "+123,456.00"
--   </pre>
--   
--   This function returns <a>Nothing</a> if the scale is less than
--   <tt>1</tt>, or if it's not possible to reliably render the decimal
--   string due to a bad choice of separators. That is, if the separators
--   are digits or equal among themselves, this function returns
--   <a>Nothing</a>.
denseToDecimal :: Approximation -> Bool -> Maybe Char -> Char -> Word8 -> Rational -> Dense currency -> Maybe Text

-- | <a>Discrete</a> represents a discrete monetary value for a
--   <tt>currency</tt> expresed as an integer amount of a particular
--   <tt>unit</tt>. For example, with <tt>currency ~ "USD"</tt> and
--   <tt>unit ~ "cent"</tt> you can represent United States Dollars to
--   their full extent.
--   
--   <tt>currency</tt> is usually a ISO-4217 currency code, but not
--   necessarily.
--   
--   Construct <a>Discrete</a> values using <a>discrete</a>,
--   <a>fromIntegral</a>, <a>fromInteger</a>, <a>discreteFromDense</a>,
--   <a>discreteFromDecimal</a>.
--   
--   For example, if you want to represent <tt>GBP 21.05</tt>, where the
--   smallest represetable unit for a GBP (United Kingdom Pound) is the
--   <i>penny</i>, and 100 <i>pennies</i> equal 1 GBP (i.e.,
--   <tt><a>Scale</a> "GBP" ~ '(100, 1)</tt>), then you can use:
--   
--   <pre>
--   <a>discrete</a> 2105 :: <a>Discrete</a> "GBP" "penny"
--   </pre>
--   
--   Because <tt>2015 / 100 == 20.15</tt>.
type Discrete (currency :: Symbol) (unit :: Symbol) = Discrete' currency (Scale currency unit)

-- | <a>Discrete'</a> represents a discrete monetary value for a
--   <tt>currency</tt> expresed as amount of <tt>scale</tt>, which is a
--   rational number expressed as <tt>(numerator, denominator)</tt>.
--   
--   You'll be using <a>Discrete</a> instead of <a>Discrete'</a> most of
--   the time, which mentions the unit name (such as <i>cent</i> or
--   <i>centavo</i>) instead of explicitely mentioning the unit scale.
data Discrete' (currency :: Symbol) (scale :: (Nat, Nat))

-- | Construct a <a>Discrete</a> value.
discrete :: GoodScale scale => Integer -> Discrete' currency scale

-- | <a>Discrete</a> currency identifier.
--   
--   <pre>
--   &gt; <a>discreteCurrency</a> (<a>discrete</a> 4 :: <a>Discrete</a> "USD" "cent")
--   "USD"
--   </pre>
discreteCurrency :: forall currency scale. (KnownSymbol currency, GoodScale scale) => Discrete' currency scale -> Text

-- | Approximate a <a>Dense</a> value <tt>x</tt> to the nearest value fully
--   representable a given <tt>scale</tt>.
--   
--   If the given <a>Dense</a> doesn't fit entirely in the <tt>scale</tt>,
--   then a non-zero <a>Dense</a> reminder is returned alongside the
--   <a>Discrete</a> approximation.
--   
--   Proof that <a>discreteFromDense</a> doesn't lose money:
--   
--   <pre>
--   x == case <a>discreteFromDense</a> a x of
--           (y, z) -&gt; <a>denseFromDiscrete</a> y + z
--   </pre>
discreteFromDense :: forall currency scale. GoodScale scale => Approximation -> Dense currency -> (Discrete' currency scale, Dense currency)

-- | Parses a decimal representation of a <a>Discrete</a>.
--   
--   Leading <tt>'-'</tt> and <tt>'+'</tt> characters are considered.
--   
--   Notice that parsing will fail unless the entire precision of the
--   decimal number can be represented in the desired <tt>scale</tt>.
discreteFromDecimal :: GoodScale scale => Maybe Char -> Char -> Rational -> Text -> Maybe (Discrete' currency scale)

-- | Render a <a>Discrete'</a> monetary amount as a decimal number in a
--   potentially lossy manner.
--   
--   This is simply a convenient wrapper around <a>denseToDecimal</a>:
--   
--   <pre>
--   <a>discreteToDecimal</a> a b c d e f (dis :: <a>Discrete'</a> currency scale)
--       == <a>denseToDecimal</a> a b c d e f (<a>denseFromDiscrete</a> dis :: <a>Dense</a> currency)
--   </pre>
--   
--   In particular, the <tt>scale</tt> in <tt><a>Discrete'</a> currency
--   scale</tt> has no influence over the scale in which the decimal number
--   is rendered. Use the <a>Rational</a> parameter to this function for
--   modifying that behavior.
--   
--   Please refer to <a>denseToDecimal</a> for further documentation.
--   
--   This function returns <a>Nothing</a> if the scale is less than
--   <tt>1</tt>, or if it's not possible to reliably render the decimal
--   string due to a bad choice of separators. That is, if the separators
--   are digits or equal among themselves, this function returns
--   <a>Nothing</a>.
discreteToDecimal :: GoodScale scale => Approximation -> Bool -> Maybe Char -> Char -> Word8 -> Rational -> Discrete' currency scale -> Maybe Text

-- | <tt><a>Scale</a> currency unit</tt> is an rational number (expressed
--   as <tt>'(numerator, denominator)</tt>) indicating how many pieces of
--   <tt>unit</tt> fit in <tt>currency</tt>.
--   
--   <tt>currency</tt> is usually a ISO-4217 currency code, but not
--   necessarily.
--   
--   The <a>Scale</a> will determine how to convert a <a>Dense</a> value
--   into a <a>Discrete</a> value and vice-versa.
--   
--   For example, there are 100 USD cents in 1 USD, so the scale for this
--   relationship is:
--   
--   <pre>
--   type instance <a>Scale</a> "USD" "cent" = '(100, 1)
--   </pre>
--   
--   As another example, there is 1 dollar in USD, so the scale for this
--   relationship is:
--   
--   <pre>
--   type instance <a>Scale</a> "USD" "dollar" = '(1, 1)
--   </pre>
--   
--   When using <a>Discrete</a> values to represent money, it will be
--   impossible to represent an amount of <tt>currency</tt> smaller than
--   <tt>unit</tt>. So, if you decide to use <tt>Scale "USD" "dollar"</tt>
--   as your scale, you will not be able to represent values such as USD
--   3.50 or USD 21.87 becacuse they are not exact multiples of a dollar.
--   
--   If there exists a canonical smallest <tt>unit</tt> that can fully
--   represent the currency in all its denominations, then an instance
--   <tt><a>Scale</a> currency currency</tt> exists.
--   
--   <pre>
--   type instance <a>Scale</a> "USD" "USD" = <a>Scale</a> "USD" "cent"
--   </pre>
--   
--   For some monetary values, such as precious metals, there is no
--   smallest representable unit, since you can repeatedly split the
--   precious metal many times before it stops being a precious metal.
--   Nevertheless, for practical purposes we can make a sane arbitrary
--   choice of smallest unit. For example, the base unit for XAU (Gold) is
--   the <i>troy ounce</i>, which is too big to be considered the smallest
--   unit, but we can arbitrarily choose the <i>milligrain</i> as our
--   smallest unit, which is about as heavy as a single grain of table salt
--   and should be sufficiently precise for all monetary practical
--   purposes. A <i>troy ounce</i> equals 480000 <i>milligrains</i>.
--   
--   <pre>
--   type instance <a>Scale</a> "XAU" "milligrain" = '(480000, 1)
--   </pre>
--   
--   You can use other units such as <i>milligrams</i> for measuring XAU,
--   for example. However, since the amount of <i>milligrams</i> in a
--   <i>troy ounce</i> (31103.477) is not integral, we need to use rational
--   with a denominator different than 1 to express it.
--   
--   <pre>
--   type instance <a>Scale</a> "XAU" "milligram" = '(31103477, 1000)
--   </pre>
--   
--   If you try to obtain the <a>Scale</a> of a <tt>currency</tt> without
--   an obvious smallest representable <tt>unit</tt>, like XAU, you will
--   get a compile error.

-- | Constraints to a scale (like the one returned by <tt><a>Scale</a>
--   currency unit</tt>) expected to always be satisfied. In particular,
--   the scale is always guaranteed to be a positive rational number
--   (<a>infinity</a> and <a>notANumber</a> are forbidden by
--   <a>GoodScale</a>).
type GoodScale (scale :: (Nat, Nat)) = (CmpNat 0 (Fst scale) ~  'LT, CmpNat 0 (Snd scale) ~  'LT, KnownNat (Fst scale), KnownNat (Snd scale))

-- | A friendly <a>TypeError</a> to use for a <tt>currency</tt> that
--   doesn't have a canonical small unit.

-- | Term-level representation of a currrency <tt>scale</tt>.
--   
--   For example, the <a>Scale</a> for <tt>"USD"</tt> in <tt>"cent"</tt>s
--   is <tt>100/1</tt>.
--   
--   <pre>
--   &gt; <a>scale</a> (<a>Proxy</a> :: <a>Proxy</a> (<a>Scale</a> "USD" "cent"))
--   100 <a>%</a> 1
--   </pre>
--   
--   <pre>
--   &gt; <a>scale</a> (x :: <a>Discrete</a> "USD" "cent")
--   100 <a>%</a> 1
--   </pre>
--   
--   The returned <a>Rational</a> is statically guaranteed to be a positive
--   number.
scale :: forall proxy scale. GoodScale scale => proxy scale -> Rational

-- | Exchange rate for converting monetary values of currency <tt>src</tt>
--   into monetary values of currency <tt>dst</tt> 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:
--   
--   <pre>
--   <a>exchangeRate</a> (12345 <a>%</a> 10000) :: <a>Maybe</a> (<a>ExchangeRate</a> "USD" "GBP")
--   </pre>
data ExchangeRate (src :: Symbol) (dst :: Symbol)

-- | Safely construct an <a>ExchangeRate</a> from a *positive*
--   <a>Rational</a> number.
exchangeRate :: Rational -> Maybe (ExchangeRate src dst)

-- | Apply the <a>ExchangeRate</a> to the given <tt><a>Dense</a> src</tt>
--   monetary value.
--   
--   Identity law:
--   
--   <pre>
--   <a>exchange</a> (<a>exchangeRateRecip</a> x) . <a>exchange</a> x  ==  <a>id</a>
--   </pre>
--   
--   Use the <i>Identity law</i> for reasoning about going back and forth
--   between <tt>src</tt> and <tt>dst</tt> in order to manage any leftovers
--   that might not be representable as a <a>Discrete</a> monetary value of
--   <tt>src</tt>.
exchange :: ExchangeRate src dst -> Dense src -> Dense dst

-- | Reciprocal <a>ExchangeRate</a>.
--   
--   This function retuns the reciprocal or multiplicative inverse of the
--   given <a>ExchangeRate</a>, leading to the following identity law:
--   
--   <pre>
--   <a>exchangeRateRecip</a> . <a>exchangeRateRecip</a>   ==  <a>id</a>
--   </pre>
--   
--   Note: If <a>ExchangeRate</a> had a <a>Fractional</a> instance, then
--   <a>exchangeRateRecip</a> would be the implementation of <a>recip</a>.
exchangeRateRecip :: ExchangeRate a b -> ExchangeRate b a

-- | Parses a decimal representation of an <a>ExchangeRate</a>.
exchangeRateFromDecimal :: Maybe Char -> Char -> Text -> Maybe (ExchangeRate src dst)

-- | Render a <a>ExchangeRate</a> as a decimal number in a potentially
--   lossy manner.
--   
--   <pre>
--   &gt; <a>exchangeRateToDecimal</a> <a>Round</a> <a>True</a> (<a>Just</a> ',') '.' 2
--         <a>=&lt;&lt;</a> (<a>exchangeRate</a> (123456 <a>%</a> 100) :: <a>Maybe</a> (<a>ExchangeRate</a> "USD" "EUR"))
--   Just "1,234.56"
--   </pre>
--   
--   This function returns <a>Nothing</a> if it is not possible to reliably
--   render the decimal string due to a bad choice of separators. That is,
--   if the separators are digits or equal among themselves, this function
--   returns <a>Nothing</a>.
exchangeRateToDecimal :: Approximation -> Maybe Char -> Char -> Word8 -> ExchangeRate src dst -> Maybe Text

-- | Obtain a <a>Rational</a> representation of the <a>ExchangeRate</a>.
--   
--   This <a>Rational</a> is guaranteed to be a positive number.
exchangeRateToRational :: ExchangeRate src dst -> Rational

-- | A monomorphic representation of <a>Dense</a> that is easier to
--   serialize and deserialize than <a>Dense</a> 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 <a>mkSomeDense</a> function.
--   
--   In order to be able to effectively serialize a <a>SomeDense</a> value,
--   you need to serialize the following three values (which are the
--   eventual arguments to <a>mkSomeDense</a>):
--   
--   <ul>
--   <li><a>someDenseCurrency</a></li>
--   <li><a>someDenseAmount</a></li>
--   </ul>
data SomeDense

-- | Convert a <a>Dense</a> to a <a>SomeDense</a> for ease of
--   serialization.
toSomeDense :: KnownSymbol currency => Dense currency -> SomeDense

-- | Build a <a>SomeDense</a> from raw values.
--   
--   This function is intended for deserialization purposes. You need to
--   convert this <a>SomeDense</a> value to a <a>Dense</a> value in order
--   to do any arithmetic operation on the monetary value.
mkSomeDense :: Text -> Rational -> Maybe SomeDense

-- | Attempt to convert a <a>SomeDense</a> to a <a>Dense</a>, provided you
--   know the target <tt>currency</tt>.
fromSomeDense :: forall currency. KnownSymbol currency => SomeDense -> Maybe (Dense currency)

-- | Convert a <a>SomeDense</a> to a <a>Dense</a> without knowing the
--   target <tt>currency</tt>.
--   
--   Notice that <tt>currency</tt> 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 <a>fromSomeDense</a>
--   directly.
withSomeDense :: SomeDense -> (forall currency. KnownSymbol currency => Dense currency -> r) -> r

-- | Currency name.
someDenseCurrency :: SomeDense -> Text

-- | Currency unit amount.
someDenseAmount :: SomeDense -> Rational

-- | A monomorphic representation of <a>Discrete</a> that is easier to
--   serialize and deserialize than <a>Discrete</a> 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 <a>mkSomeDiscrete</a> function.
--   
--   In order to be able to effectively serialize a <a>SomeDiscrete</a>
--   value, you need to serialize the following four values (which are the
--   eventual arguments to <a>mkSomeDiscrete</a>):
--   
--   <ul>
--   <li><a>someDiscreteCurrency</a></li>
--   <li><a>someDiscreteScale</a></li>
--   <li><a>someDiscreteAmount</a></li>
--   </ul>
data SomeDiscrete

-- | Convert a <a>Discrete</a> to a <a>SomeDiscrete</a> for ease of
--   serialization.
toSomeDiscrete :: (KnownSymbol currency, GoodScale scale) => Discrete' currency scale -> SomeDiscrete

-- | Internal. Build a <a>SomeDiscrete</a> from raw values.
--   
--   This function is intended for deserialization purposes. You need to
--   convert this <a>SomeDiscrete</a> value to a <a>Discrete</a> vallue in
--   order to do any arithmetic operation on the monetary value.
mkSomeDiscrete :: Text -> Rational -> Integer -> Maybe SomeDiscrete

-- | Attempt to convert a <a>SomeDiscrete</a> to a <a>Discrete</a>,
--   provided you know the target <tt>currency</tt> and <tt>unit</tt>.
fromSomeDiscrete :: forall currency scale. (KnownSymbol currency, GoodScale scale) => SomeDiscrete -> Maybe (Discrete' currency scale)

-- | Convert a <a>SomeDiscrete</a> to a <a>Discrete</a> without knowing the
--   target <tt>currency</tt> and <tt>unit</tt>.
--   
--   Notice that <tt>currency</tt> and <tt>unit</tt> 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
--   <a>fromSomeDiscrete</a> directly.
--   
--   Notice that you may need to add an explicit type to the result of this
--   function in order to keep the compiler happy.
withSomeDiscrete :: forall r. SomeDiscrete -> (forall currency scale. (KnownSymbol currency, GoodScale scale) => Discrete' currency scale -> r) -> r

-- | Currency name.
someDiscreteCurrency :: SomeDiscrete -> Text

-- | Positive, non-zero.
someDiscreteScale :: SomeDiscrete -> Rational

-- | Amount of currency unit.
someDiscreteAmount :: SomeDiscrete -> Integer

-- | A monomorphic representation of <a>ExchangeRate</a> that is easier to
--   serialize and deserialize than <a>ExchangeRate</a> 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 <a>mkSomeExchangeRate</a>
--   function.
--   
--   In order to be able to effectively serialize an
--   <a>SomeExchangeRate</a> value, you need to serialize the following
--   four values (which are the eventual arguments to
--   <a>mkSomeExchangeRate</a>):
--   
--   <ul>
--   <li><a>someExchangeRateSrcCurrency</a></li>
--   <li><a>someExchangeRateDstCurrency</a></li>
--   <li><a>someExchangeRateRate</a></li>
--   </ul>
data SomeExchangeRate

-- | Convert a <a>ExchangeRate</a> to a <a>SomeDiscrete</a> for ease of
--   serialization.
toSomeExchangeRate :: (KnownSymbol src, KnownSymbol dst) => ExchangeRate src dst -> SomeExchangeRate

-- | Internal. Build a <a>SomeExchangeRate</a> from raw values.
--   
--   This function is intended for deserialization purposes. You need to
--   convert this <a>SomeExchangeRate</a> value to a <a>ExchangeRate</a>
--   value in order to do any arithmetic operation with the exchange rate.
mkSomeExchangeRate :: Text -> Text -> Rational -> Maybe SomeExchangeRate

-- | Attempt to convert a <a>SomeExchangeRate</a> to a <a>ExchangeRate</a>,
--   provided you know the target <tt>src</tt> and <tt>dst</tt> types.
fromSomeExchangeRate :: forall src dst. (KnownSymbol src, KnownSymbol dst) => SomeExchangeRate -> Maybe (ExchangeRate src dst)

-- | Convert a <a>SomeExchangeRate</a> to a <a>ExchangeRate</a> without
--   knowing the target <tt>currency</tt> and <tt>unit</tt>.
--   
--   Notice that <tt>src</tt> and <tt>dst</tt> 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
--   <a>fromSomeExchangeRate</a> directly.
withSomeExchangeRate :: SomeExchangeRate -> (forall src dst. (KnownSymbol src, KnownSymbol dst) => ExchangeRate src dst -> r) -> r

-- | Source currency name.
someExchangeRateSrcCurrency :: SomeExchangeRate -> Text

-- | Destination currency name.
someExchangeRateDstCurrency :: SomeExchangeRate -> Text

-- | Exchange rate. Positive, non-zero.
someExchangeRateRate :: SomeExchangeRate -> Rational

-- | Method for approximating a fractional number to an integer number.
data Approximation

-- | Approximate <tt>x</tt> to the nearest integer, or to the nearest even
--   integer if <tt>x</tt> is equidistant between two integers.
Round :: Approximation

-- | Approximate <tt>x</tt> to the nearest integer less than or equal to
--   <tt>x</tt>.
Floor :: Approximation

-- | Approximate <tt>x</tt> to the nearest integer greater than or equal to
--   <tt>x</tt>.
Ceiling :: Approximation

-- | Approximate <tt>x</tt> to the nearest integer betwen <tt>0</tt> and
--   <tt>x</tt>, inclusive.
Truncate :: Approximation
