Skip to content

Conversation

@chiphogg
Copy link
Member

@chiphogg chiphogg commented Feb 5, 2026

UnitSum<...> takes a bunch of input units, and produces the canonical
type that represents their sum. Usually, this will be a unit, but it
could also be Zero. Core tasks include:

  • Unpacking any inputs that are already UnitSumPack<...>;
  • Identifying unique "unscaled units"
  • Collecting like terms
  • Eliminating groups of unscaled units that get "zeroed out"
  • Putting what's left in the right order
  • Handling cases where only 0 or 1 units are left

The main subtlety has to do with when the overall unit completely
cancels out. The result is not-a-unit: it is equivalent to Zero.
When every individual group of unscaled units cancels out, then it's
very easy for us to actually return Zero. But, philosophically, we
have avoided the implementation complexity of looking "extra hard" for
cancellation in cases such as s * Hz, for example. Taking a similar
tack here means that we could produce a result like (ft - 12 in),
which is 0, but is not Zero, and which would act really weird if we
used it like a unit.

For now, I think the conservative approach is to make this a compiler
error. I really doubt there are true use cases for this. I plan to
simply tell users not to form any Constant sum that adds to zero,
regardless of whether or not the library would call it Zero. We can
change this later if we come up with an elegant and simple formulation,
and/or if somebody provides a really compelling use case. But starting
out with this pathway means that we won't break any existing code, and
a future upgrade that would allow this would also not break any
existing code.

Helps #607.

`UnitSum<...>` takes a bunch of input units, and produces the canonical
type that represents their sum.  Usually, this will be a unit, but it
could also be `Zero`.  Core tasks include:

- Unpacking any inputs that are already `UnitSumPack<...>`;
- Identifying unique "unscaled units"
- Collecting like terms
- Eliminating groups of unscaled units that get "zeroed out"
- Putting what's left in the right order
- Handling cases where only 0 or 1 units are left

The main subtlety has to do with when the overall unit completely
cancels out.  The result is not-a-unit: it is equivalent to `Zero`.
When every individual group of unscaled units cancels out, then it's
very easy for us to actually return `Zero`.  But, philosophically, we
have avoided the implementation complexity of looking "extra hard" for
cancellation in cases such as `s * Hz`, for example.  Taking a similar
tack here means that we could produce a result like `(ft - 12 in)`,
which is 0, but is not `Zero`, and which would act really weird if we
used it like a unit.

For now, I think the conservative approach is to make this a compiler
error.  I really doubt there are true use cases for this.  I plan to
simply tell users not to form _any_ `Constant` sum that adds to zero,
regardless of whether or not the library would call it `Zero`.  We can
change this later if we come up with an elegant and simple formulation,
and/or if somebody provides a really compelling use case.  But starting
out with this pathway means that we won't break any existing code, _and_
a future upgrade that would allow this would _also_ not break any
existing code.

Helps #607.
@chiphogg chiphogg merged commit fe4ede1 into main Feb 6, 2026
27 checks passed
@chiphogg chiphogg deleted the chiphogg/unit-sum#607 branch February 6, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants