finanza/currency

Currency and money types built on top of finanza/decimal.

A Currency is a small record describing an ISO 4217 alpha-3 code together with display metadata. A Money pairs a Decimal amount with a Currency so arithmetic that crosses currencies is rejected with a typed error.

Both types are pub opaque. Build them through the smart constructors new_currency and new (for Money), or pick a catalogue value from finanza/currency/catalog.

Types

A monetary unit identified by an ISO 4217 alpha-3 code.

pub opaque type Currency

Errors raised by currency and money operations.

pub type CurrencyError {
  CurrencyMismatch(left: String, right: String)
  InvalidExponent
  InvalidCurrencyCode
  EmptyRatios
  NonPositiveRatio
  ArithmeticError(error: decimal.ArithmeticError)
}

Constructors

  • CurrencyMismatch(left: String, right: String)

    Two operands had different currencies.

  • InvalidExponent

    exponent passed to new_currency was out of the supported range (0–8).

  • InvalidCurrencyCode

    code passed to new_currency was empty.

  • EmptyRatios

    allocate was called with an empty ratio list.

  • NonPositiveRatio

    allocate received a ratio that was zero or negative.

  • ArithmeticError(error: decimal.ArithmeticError)

    A decimal operation overflowed the supported precision window. Inspect error for the underlying decimal error.

Options passed to format. Build from default_format and the with_* setters.

pub opaque type FormatOptions

An amount denominated in a particular Currency.

pub opaque type Money

How negative amounts are rendered in formatted output.

pub type NegativeStyle {
  MinusSign
  Parentheses
}

Constructors

  • MinusSign
  • Parentheses

Where the currency symbol appears in formatted output.

pub type SymbolPosition {
  Prefix
  Suffix
  NoSymbol
}

Constructors

  • Prefix
  • Suffix
  • NoSymbol

Values

pub fn add(
  a a: Money,
  b b: Money,
) -> Result(Money, CurrencyError)

Add two Money values. Both operands must share the same currency.

pub fn allocate(
  m m: Money,
  ratios ratios: List(Int),
) -> Result(List(Money), CurrencyError)

Split a Money proportionally to ratios, distributing rounding remainders to the first slots so the slices sum back to the original amount exactly.

let bill = from_minor(units: 1000, currency: catalog.usd())
allocate(bill, [1, 1, 1])
// Ok([$3.34, $3.33, $3.33])
pub fn amount(m m: Money) -> decimal.Decimal

The amount component of a Money.

pub fn code(c c: Currency) -> String

ISO 4217 alpha-3 code (e.g. "USD").

pub fn compare(
  a a: Money,
  b b: Money,
) -> Result(order.Order, CurrencyError)

Compare two money values. Both operands must share the same currency.

pub fn currency_of(m m: Money) -> Currency

The currency component of a Money. Named currency_of to avoid a currency.currency(m) call site, which reads awkwardly given the module name.

pub fn default_format() -> FormatOptions

Default FormatOptions: symbol prefix, , thousands separator, . decimal separator, leading minus sign, no currency code suffix, and the amount is rescaled to the currency’s minor-unit exponent (so USD always renders with two cents, JPY with none, etc.).

pub fn divide(
  m m: Money,
  divisor divisor: decimal.Decimal,
  mode mode: rounding.Mode,
) -> Result(Money, CurrencyError)

Divide a money value by a scalar, rounding the result to the currency’s minor-unit exponent using mode.

pub fn equal(a a: Money, b b: Money) -> Bool

Equality test for two money values. Returns False rather than an error on currency mismatch, mirroring ==.

pub fn exponent(c c: Currency) -> Int

Minor-unit exponent (USD = 2, JPY = 0, BHD = 3, etc.).

pub fn format(
  m m: Money,
  options options: FormatOptions,
) -> String

Render a money value with the given FormatOptions.

By default the amount is rescaled to the currency’s minor-unit exponent (so 12 renders as `12.00and ¥1234 as¥1,234). Call [with_minor_units](#with_minor_units) with False` to preserve the amount’s original precision.

pub fn from_minor(
  units units: Int,
  currency currency: Currency,
) -> Money

Build a Money from an integer number of minor units. The resulting amount has exponent -currency.exponent.

from_minor(units: 1234, currency: catalog.usd()) represents $12.34.

pub fn multiply(
  m m: Money,
  factor factor: decimal.Decimal,
) -> Result(Money, CurrencyError)

Multiply a money value by a scalar.

pub fn name(c c: Currency) -> String

English-language name of the currency.

pub fn negate(m m: Money) -> Money

Negate a money value.

pub fn new_currency(
  code code: String,
  exponent exponent: Int,
  symbol symbol: String,
  name name: String,
) -> Result(Currency, CurrencyError)

Build a custom Currency. Use this when the desired currency is outside the static catalogue.

code must be a non-empty string. exponent is the number of minor-unit digits and must be in the range 0–8.

pub fn new_money(
  amount amount: decimal.Decimal,
  currency currency: Currency,
) -> Money

Build a Money from a Decimal and a Currency. Named new_money rather than new to keep symmetry with new_currency and to avoid the surprise of currency.new returning the other type from the module’s name.

pub fn subtract(
  a a: Money,
  b b: Money,
) -> Result(Money, CurrencyError)

Subtract b from a.

pub fn symbol(c c: Currency) -> String

Display symbol (e.g. "$", "¥").

pub fn to_minor(
  m m: Money,
  mode mode: rounding.Mode,
) -> Result(Int, CurrencyError)

Convert a Money back to its minor-unit integer count, rounding to the currency’s exponent using mode.

pub fn to_string(m m: Money) -> String

Render a money value using the default ISO-style format: "USD 1234.56".

pub fn with_currency_code(
  options options: FormatOptions,
  enabled enabled: Bool,
) -> FormatOptions

Toggle whether the ISO code is appended to the rendered string.

pub fn with_decimal_separator(
  options options: FormatOptions,
  separator separator: String,
) -> FormatOptions

Override the decimal separator.

pub fn with_minor_units(
  options options: FormatOptions,
  enabled enabled: Bool,
) -> FormatOptions

Toggle whether the amount is rescaled to the currency’s minor-unit exponent before rendering. Defaults to True; pass False to preserve the amount’s original precision (useful when the value carries finer-than-minor digits, e.g. for an FX rate or a unit price).

pub fn with_negative_style(
  options options: FormatOptions,
  style style: NegativeStyle,
) -> FormatOptions

Override the negative-amount style.

pub fn with_symbol_position(
  options options: FormatOptions,
  position position: SymbolPosition,
) -> FormatOptions

Override the symbol position.

pub fn with_thousands_separator(
  options options: FormatOptions,
  separator separator: String,
) -> FormatOptions

Override the thousands separator.

Search Document