Implicit Conversion from Quantity[V, U] to V #668
Replies: 3 comments 5 replies
-
Hi @benhutchison ! I took a look at Iron back when you suggested it. I found it quite interesting. There are some extra considerations for Quantity, and problems with implicit conversions to Value (I can no longer remember the details, and frankly changes to Scala periodically cause me new problems or fix old ones). I briefly tried declaring One example of what I predict would be a problem is something like val x: Quantity[Double, Meter] ...
val y: Quantity[Double, Yard] ...
// will this be treated as Double, or Quantity[Double, Meter] ? Or will the compiler fail?
x + y |
Beta Was this translation helpful? Give feedback.
-
Indeed. If Scala's math operators were consistently typeclass-based, I
believe it could be made to work, because there is a rule that Scala
compiler prefers/selects more specific (ie subtype) typeclass instances
over more general (supertype) ones, without ambiguity. So Quantity[V, U]
operators would be chosen before V operators.
However, Scala is an awkward hybrid of object-orientation and typeclasses,
and OO overrides typeclasses. Since core primitives like Double have OO-
style operators baked in, they're a minefield for typeclass-based extension.
As you point out, one option is to move typeclass operators to a
non-congested namespace, like `++`. My taste is actually for a consistent
hash-prefix, as in `#+`, `#-`, `#*` etc, where hash signifies a switch off
built-ins and to fully typeclass-based APIs.
One potential appeal of implicit conversion from Quantity[V, _] to V is
their "reluctance", so that Quantity + Quantity would presumably resolve
before triggering conversion to V.
Now if I thinking back to my actual use case,
`o.size.value.roundSigDecimalPlaces(3)`, I didn't want to stop being a
Quantity, I just wanted to trim excessive decimal places for
human-readability in a report, and I had an operator
`roundSigDecimalPlaces` for BigDecimal already.
So a `transform(f: V => V)` operation over a Quantity would have served
this specific case. Up-conversion via `.value` works, but throws away the
quantity tag unnecessarily.
What I don't want to do is define lots of extension methods for Quantity[V,
_] that forward to V, that seems like busywork.
…On Tue, Apr 22, 2025 at 9:04 AM Erik Erlandson ***@***.***> wrote:
So, my suspicion was correct: trying to define a specialized + operator
compiles, but is ignored in favor of just using + for Double. If I define
a ++ operator, that works as desired, since there is nothing else to
conflict with it:
scala> 1.0.withUnit2[Meter]val res0: coulomb.Quantity2[Double, coulomb.units.si.Meter] = 1.0
scala> 1.0.withUnit2[Yard]val res1: coulomb.Quantity2[Double, coulomb.units.us.Yard] = 1.0
scala> res0 + res1val res2: Double = 2.0
scala> res0 ++ res1val res3: coulomb.Quantity2[Double, coulomb.units.si.Meter] = 1.9144
—
Reply to this email directly, view it on GitHub
<#668 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAXJZCJIVSCFZJOIRIXRUT22V2P5AVCNFSM6AAAAAB3RGVZX6VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTEOJQGM4TMNA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I think a map-like operator would be useful*, but I'm not sure if Quantity
can support full Functor map A=> B semantics, ie map to any type B?
That's why I speculated the more limited V =≥ V transform that stays within
the same value representation.
* Actually I defined an extension method on Quantity, mapV for this purpose
yesterday
…On Tue, 22 Apr 2025, 11:39 pm Erik Erlandson, ***@***.***> wrote:
I could provide a map function. I've toyed with the idea of trying to
make Quantity a monad, or at least monad-like, on and off. The type
signature [V, U] prevents it from being a true Scala monad.
—
Reply to this email directly, view it on GitHub
<#668 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAXJZH75XFBCTC4EILL5Y322ZBBBAVCNFSM6AAAAAB3RGVZX6VHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTEOJRGA3TMMA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi Erik 👋
Long time no see, well.. talk. I'm not sure if I mentioned but I've been quite diverted by the birth of my daughter Ava, who is currently 4 months old.
But today I was dusting off some code built on top of Coulomb and fixing some issues.
And not for the first time, I found myself unwrapping Quantities to transform the value, writing
o.size.value.roundSigDecimalPlaces(3)
, where size has typeQuantity[BigDecimal, UAsset]
. Actually when I look my codebase is already littered with places where I unwrap quantities.Meanwhile, in recent times I've also been using Iron for Refined Types, and enjoying the techniques described here to make refined types a proper subtype of their unrefined type.
And I'm becoming more inclined to view that as the correct, normal way that refinement should be approached. A refined type should be a subtype of the unrefined type, but different refinements shouldn't be substitutable for each other.
Extending that idea to Coulomb would be to view
Quantity[V, U]
as aV
with additional refinements.Now this paradigm would let us add unrelated units, eg Minutes and Metres, where the addition operation happens by jumping up to the raw value layer. But in that case the units are lost in the result.
When I think about what I really want Coulomb's types to prevent, it's actually not to stop me from adding Minutes and Metres, but rather to prevent me mistakenly using the result as some dimensioned quantity. And the type ascriptions on method parameters, values etc, ought to block that.
I forget if we ever talked about an implicit conversion from
Quantity[V, U]
toV
? I have some vague memory of it... maybe it was present in an earlier version of Coulomb and was troublesome, or maybe it's there now as an opt-in thing? I couldn't see any mention in the documentation from a quick scan tonight.Beta Was this translation helpful? Give feedback.
All reactions