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