Currently, there is only one solution for min and max in library(aggregate), regardless if we use aggregate/3 or aggregate_all/3. (or the 4-argument version with the discriminator). Here is what I mean:
foo(1, a). foo(2, b). foo(3, c). foo(3, a).
?- aggregate_all(max(A, B), foo(A, B), Max). Max = max(3, c).
I don’t see any way to collect both values in the second argument associated with 3, the maximum of the first argument.
I assume this is a conscious decision when developing the library. Still, how would I do it? The best at the moment (short of writing my own aggregation) is to first find the max, then findall using the value:
?- aggregate_all(max(A), foo(A, _), Max), findall(B, foo(Max, B), Bs). Max = 3, Bs = [c, a].
This is fine, but not ideal?
I would have proposed an extension to library(aggregate); for what I see, it means adding a case for new value equal to the min or max, for example here in the aggregate_all definition.
But I cannot figure out a clean interface for this that doesn’t break the current behaviour.
So how would I do this? The silent assumption is that if I have a backtrackable predicate, I don’t necessarily want to collect everything to a list. The best I can come up with is write my own aggregation, using the code in library(aggregate) as an inspiration.