AmountFormatExt: central place to explain why we use the somewhat redundant allCommodities parameter - #2730
AmountFormatExt: central place to explain why we use the somewhat redundant allCommodities parameter#2730thielema wants to merge 1 commit into
Conversation
…e use the somewhat redundant allCommodities parameter The type highlights the connection between allCommodities and AmountFormat. multiBalanceRowAsCsvText: swap order of parameters since allCommodities plays the role of AmountFormat here.
|
I'm not too keen on this. I think just a comment would give more bang for the buck. |
|
On Sun, 13 Sep 2026, Simon Michael wrote:
[10144?s=20&v=4] simonmichael left a comment (hledgerorg/hledger#2730)
I'm not too keen on this. I think just a comment would give more bang for the buck.
A simple comment isn't as easy as it looks first. I need to choose a place
where to attach the comment such that it is found when someone wonders.
There are two functions that are candidates for the comment, but maybe
even the callers are the better place. And the other places have to refer
to that comment in order to not get missed, right?
I think the Clean Coders are right here: Better try to make code clearer
by primary language features. Thus I am quite happy with the type synonym
solution.
|
|
Agreed, but I'm not convinced this makes things clearer. Mine is only a gut feeling, but here are some more specifics from ai:
|
|
On Sun, 13 Sep 2026, Simon Michael wrote:
Agreed, but I'm not convinced this makes things clearer.
Mine is only a gut feeling, but here are some more specifics from ai:
The type synonym adds no safety. AmountFormatExt is just a name
for a tuple — the compiler accepts any (AmountFormat,
[CommoditySymbol]) pair, including a wrong or empty list, so the
unenforced invariant is exactly as unenforced as before.
The invariant is unenforced and I am afraid Haskell's type system is not
strong enough to enforce that invariant. Liquid Haskell could do these
kind of things, but for my judgement is not yet production ready.
However, giving a list with missing commodity symbols can be even used as
feature, namely as a commodity filter.
That said, the problem with the unenforced invariant arises only for the
report builders were I export partial builders for re-use in
CompoundBalanceCommand. In the complete builders, allCommodities is just a
local variable.
I offer to move those partial builders and other helper functions to a
private module, say BalancePrivate.hs. This is a good idea anyway to
remove distraction for users of the library interface.
|
…outs setDisplayCommodityBare installs a commodity order that orderedAmounts renders one amount per entry of, silently dropping amounts in unlisted commodities. Say so there, and point to it from the two functions that gather the LayoutBareWide commodity list. Related to #2728, #2730 AI usage: Claude Fable 5.1, ~6k output tokens
|
Sorry, I don't think the tuple adds clarity here. I have pushed some comments instead. If you think the private module is a win, let's try that as a new PR. I think typical haskell naming would be .Internal ? I'm not quite seeing the benefit of complicating our module tree, given that we can control visibility with exports (and we don't have many library users). |
|
On Mon, 21 Sep 2026, Simon Michael wrote:
[10144?s=20&v=4] simonmichael left a comment (hledgerorg/hledger#2730)
Sorry, I don't think the tuple adds clarity here. I have pushed some comments instead.
If you think the private module is a win, let's try that as a new PR. I
think typical haskell naming would be .Internal ? I'm not quite seeing
the benefit of complicating our module tree, given that we can control
visibility with exports (and we don't have many library users).
We have some functions, that shall be used by functions in
Cli.Commands.Balance and CompoundBalanceCommand but shall not be
externally visible. How would you solve this without an additional private
module?
|
|
I see. I could also just export from Balance with special naming and haddock, as a special case. But I see your point. |
The type highlights the connection between
allCommoditiesandAmountFormat.multiBalanceRowAsCsvText: swap order of parameters since allCommodities plays the role of AmountFormat here.This is my proposal to address this objection in a non-invasive way:
#2728 (comment)
Since
allCommoditiesis only needed forLayoutBareWidewe could add an according parameter to theLayoutBareWideconstructor. But then we would likely need a type parameter forLayoutfor theLayoutBareWide-associated data since we do not always want to carry a[CommoditySymbol].We could split
AmountFormatinto a smaller type for report generating functions and a larger type forshowMixedAmountWith& Co. The larger type could carry the smaller one in a record field.Both are pretty invasive changes, though.