Closed JimLarson closed 2 years ago
This is a great idea imo, just will need a clear comment so people realize that the following can pass:
c := A.Min(B)
assert c != A && c != B
Perhaps this can be done by calling it "MinSet" or something? (Surely theres some standard naming for taking the entry-wise minimum of two lists)
Feel free to tag me as a reviewer for such a PR
The literature seems to call this "multiset intersection" or "bag intersection", or "infemum" or "greatest common divisor". See wikipedia entry.
I can definitely document it clearly. For a name, let me see how it looks in context. Briefer seems better. So far, Min()
seems the most intuitive, but maybe Inf()
is just as good?
Oh can we call it intersection?
If we prefer a 3-4 letter name, then Min
also SGTM
If we call this Intersection()
, we'd want to rename IsAllGTE()
to Contains()
to be consistent. :-)
But I think we'll want to stick with an "ordering" theme rather than a "set theory" theme. The latter is technically correct, but I don't think it's how we think about Coins
.
I'll try to find some places to use this in the codebase, so seeing the uses in context will help with the naming discussion.
Ok that sounds good to me! I'm down for Min
under this framing. (Using an ordering interpretation rather than a set theory one)
I don't think theres harm in duplicate functions for both SetTheory naming + normal naming, but we can easily make that a separate issue after Min()
is in
@ValarDragon I've tagged you on #11200 which is in draft form, per CONTRIBUTING.md
. Please advise on next steps.
Note that sdk.DecCoins
has an Intersect()
call with the same semantics as Min()
. I'll add it as another name for Min()
.
See #11223 for other changes which could make Coins
and DecCoins
more consistent.
Summary
Incorporate a new
Coins
method:func (c Coins) Min(other Coins) Coins
for utility and consistency.Problem Definition
When working with
Coins
, it's sometimes useful to compute the minimum of two values, defined as the minimum of each denom, but there's no existing library method for it.Example:
toTransfer := want.Min(spendable)
Example: to computemax(a.Sub(b), zeroCoin)
without panicking, computea.Sub(a.Min(b))
With
IsAllLTE()
defining a partial order onCoins
,Min()
becomes the "meet" operator of a lattice, tying the operations into centuries of mathematical precedent.Proposal
Implement
func (c Coins) Min(other Coins) Coins
with tests and documentation for its properties.Max()
should be added for symmetry, with the property thata.Add(b) == (a.Max(b)).Add(a.Min(b))
, so it could be defined asWhere
0
is the emptyCoins
value,<=
isIsAllLTE()
, and==
is a non-panicking variant ofIsEqual()
, for arbitraryCoins
valuesa
,b
, andc
, we have the properties:<=
is a partial order:a <= a
a <= b && b <= a
implya == b
a <= b && b <= c
implya <= c
Min()
is the greatest lower bound ("meet") with respect to this order, andMax()
is the least upper bound ("join"):a <= b
if and only ifa.min(b) == a && a.max(b) == b
Min()
andMax()
are commutative and associativea.Max(a.Min(b)) == a
a.Min(a.Max(b)) == a
a.Max(b.Min(c)) == a.Max(b).Min(a.Max(c))
a.Min(b.Max(c)) == a.Min(b).Max(a.Min(c))
0
is the bottom element0.Min(a) == 0
0.Max(a) == a
For Admin Use