What world is

world gives Scala the concepts commerce actually runs on, as types that compute exactly and carry their own reference data:

  • civil time - a day that is not tied to one calendar's labelling, with arithmetic whose overflow policy is named at the call site
  • places and locales - territories, regions, languages, scripts, and BCP 47 tags, with negotiation against a supported set
  • money - amounts closed over their currency, tax structures, graduated bands, and legally-correct cash rounding
  • quantities - measures and unit prices, block tariffs, and rate cards
  • identifiers - bank, telephone, and internet identifiers checked as far offline as their standards allow, over a scheme concept your own registrations declare against
  • addresses - postal addresses structured, validated, and printed by the territory's own rules, with the coordinate a pin-addressed delivery carries
  • parties - the person or organisation a document is addressed to, with their names, contacts, addresses, and registrations on one value

Every module cross-publishes for the JVM, Scala.js, and Scala Native. Territory, language, script, currency, and locale facts are curated from their issuing authorities and compiled into the artefacts, so behaviour does not change underneath you when a platform, a JDK, or a browser does.

Add it

libraryDependencies += "africa.shuwari" %%% "world" % "@VERSION@"

Modules and coordinates lists the full set and its dependency graph.

What the types guarantee

Errors are values. Every operation that can fail returns Either over a sealed family rooted at WorldError. Nothing throws. A failure's message names the violated constraint; the value that violated it stays a typed field, so captured input never reaches a log through getMessage.

Arithmetic is exact, and rounding is never silent. Money and quantities compute over exact decimals and rationals. Every operation whose result need not terminate takes the scale and the mode at the call site.

Wrong combinations do not compile. Money is parameterised by its currency, quantities by their kind, and exchange rates by their direction. Binary floating-point is refused at every exact-numeric seam with a message pointing at the decimal form.

// Currency.KES(1) + Currency.TZS(2)      does not compile
// Currency.KES(1.5)                      does not compile
// Measure.Kilogram(1) + Measure.Litre(1) does not compile

Data is versioned, not ambient. Each dataset records the upstream release it was taken from, so an artefact can state which vintage of each source it holds. See the data that ships.

Where to go next

If you are Start at
pricing, invoicing, or taking payment Money and pricing
weighing, measuring, or metering Quantities and tariffs
handling dates, ages, or calendars Civil time and calendars
localising, or resolving territories Places, locales, and currencies
capturing bank, telephone, or email identifiers Identifiers and schemes
capturing or printing postal addresses Addresses and coordinates
modelling customers, suppliers, or counterparties Names, organisations, and parties
showing any of it to a person Presenting values to people
deciding what to redact or retain Personal data
changing world itself Contributing

Status

Pre-release and under active development. Expect API changes.

Licence

Licensed under the Apache Licence, Version 2.0.