From c90ff5253efd858a2bf0c20eaa2ee9763a402783 Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Mon, 9 Mar 2026 22:29:18 +0100 Subject: oha! --- lib/balanced_batch.ml | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 lib/balanced_batch.ml (limited to 'lib/balanced_batch.ml') diff --git a/lib/balanced_batch.ml b/lib/balanced_batch.ml new file mode 100644 index 0000000..5a64546 --- /dev/null +++ b/lib/balanced_batch.ml @@ -0,0 +1,42 @@ +open Prelude + +(* Degenerate transactions, which can be applied directly to account + hierarchies (because we ideally want no unsafe operations on + accounts) *) +module Make (K : Map_intf.Key) : sig + type entry = { + dc : Money.Debit_credit.t; + commodity : Money.Commodity_id.t; + amount : Money.Amount.t; + } + + type t + type error = Unbalanced + + val make : entry Map.Make(K).t -> (t, error) result + val entries : t -> entry Map.Make(K).t +end = struct + type entry = { + dc : Money.Debit_credit.t; + commodity : Money.Commodity_id.t; + amount : Money.Amount.t; + } + + type t = entry Map.Make(K).t + type error = Unbalanced + + let is_balanced entries = + Map.fold entries ~init:Money.Commodity_id.Map.empty + ~f:(fun ~key:_ ~data comm_balances -> + Map.update comm_balances data.commodity ~f:(fun ocomm_bal -> + let comm_bal = Option.value ocomm_bal ~default:Money.Diff.(~$0) in + match data.dc with + | Money.Debit_credit.Debit -> Money.Diff.(comm_bal +% data.amount) + | Money.Debit_credit.Credit -> Money.Diff.(comm_bal -% data.amount))) + |> Map.for_all ~f:(fun comm_bal -> Money.Diff.(comm_bal = ~$0)) + + let make entries = + if not (is_balanced entries) then Error Unbalanced else Ok entries + + let entries entries = entries (* ambiguous? I disagree *) +end -- cgit v1.3