money.sum
Total a list of monetary amounts, with an explicit currency for the empty case.
1.0.1 · published 2026-10-03 by charlie · Anterra
Pinned by 11 tests, run in TypeScript, Python and Rust.
What it does
The currency argument looks redundant until the list is empty, which is exactly when `reduce` without an initial value throws in production.
1.0.1 adds tests; behaviour unchanged.
For example
sum_money(£10.00, £25.50, £0.99, GBP)→ £36.49 totals three linessum_money(, GBP)→ £0.00 empty list is zero in the stated currencysum_money(£50.00, -£12.00, GBP)→ £38.00 credits reduce the total
The function
The same function in TypeScript, Python and Rust, pinned by the same tests. Pick your language; the choice follows you around the registry.
def sum_money(amounts: Sequence[Money], currency: str) -> Money
| amounts | Money[] | |
| currency | string | the currency of the result, required so an empty list still has one |
| returns | Money |
Your code names it in one line, in the file that uses it
from fune.money.sum import sum_money # money.sum@^1
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
from typing import Iterable
from .money_add import add_money ← from money.add ^1.0.0 · built alongside by fune
from .money_amount import Money, money ← from money.amount ^1.0.0 · built alongside by fune
def sum_money(amounts: Iterable[Money], currency: str) -> Money:
total = money(0, currency)
for amount in amounts:
total = add_money(total, amount)
return totalInstall
fune build
With that line in your source, in a Python project (language python in fune.project), fune build resolves it and its 2 dependencies, pins them in fune.lock, downloads only the Python package of each, and builds the code above into your project’s .fune/build, one readable file per capability with a header linking back here. Or pin a range in fune.project and build in one step:
fune add money.sum
The manifest, vectors and README with only the Python implementation. Install it without the registry with fune add ./money.sum-1.0.1-python.fune, or fetch it from a terminal with fune pull money.sum@1.0.1:python.
The whole function, every language, is one file too: money.sum-1.0.1.fune, 5,305 bytes, sha256 b10d69d8451e8785f2c24dd1321240ee289aef491bedae6c2419b38984e03a02. It installs into a project of any language.
Customise it in your app
The seams this capability offers. Put a marker directly above a function of your own and fune build wires it into the built code; the package on the registry is not changed, the built file’s header lists it under CUSTOMISED, and fune hooks lists every hook in the project. How hooks work.
before — your function gets the arguments and returns them, changed or not, or throws to refuse the call.
# fune: before money.sum
after — your function gets the result and the arguments, and returns the final result.
# fune: after money.sum
replace — inside this capability’s code only, calls to a dependency go to your function, with the same signature. Other capabilities that use it are unaffected; write in * to replace it everywhere.
# fune: replace money.add in money.sum
# fune: replace money.amount in money.sum
step — your function runs at a numbered point inside the function’s body, receives the in-scope values it names as parameters, and may return replacements. List the points with fune show money.sum --steps.
# fune: step money.sum after <n|label>
Tests
A version published now needs at least 8 tests for every function, and one that expects the error for each function that throws; the registry refuses it otherwise. fune verify --all runs each case in TypeScript, Python and Rust, and a project runs them again with fune verify. This page lists the cases; it does not run them. The exact JSON is vectors.json.
| Case | Arguments | Expected | |
|---|---|---|---|
| totals three lines | £10.00, £25.50, £0.99, GBP | → | £36.49 |
| empty list is zero in the stated currency | , GBP | → | £0.00 |
| credits reduce the total | £50.00, -£12.00, GBP | → | £38.00 |
| a foreign amount in the list is an error | £1.00, $1.00, GBP | → | error: currency mismatch |
| one amount is its own total | €2.50, EUR | → | €2.50 |
| an empty list in a zero-decimal currency | , JPY | → | ¥0 |
| credits can take the total below zero | £10.00, -£15.00, GBP | → | -£5.00 |
| ten 10p amounts make exactly one pound | £0.10, £0.10, £0.10, £0.10, £0.10, £0.10, £0.10, £0.10, £0.10, £0.10, GBP | → | £1.00 |
| large totals stay exact up to the largest safe integer | £90,071,992,547,400.00, £9.90, £0.01, GBP | → | £90,071,992,547,409.91 |
| every amount must be in the stated currency, not the first one's | €1.00, €2.00, GBP | → | error: currency mismatch |
Show the other 1 test
| Case | Arguments | Expected | |
|---|---|---|---|
| an invalid currency is refused even for an empty list | , gbp | → | error: ISO 4217 |
Files
| Path | Bytes |
|---|---|
| README.md | 194 |
| impl/python.py | 284 |
| impl/rust.rs | 590 |
| impl/typescript.ts | 276 |
| vectors.json | 2,272 |