I have hit a problem while working with the Units of Measurements functionality in metascala, defined in the file Units.scala.
For the remainder of this question, I will use a simplified scheme, with only one Unit type, length.
So where in reality a type looks like
Quantity[_1, _0, _0, _0, _0, _0, _0]
^ ^ ^ ^ ^ ^ ^
| | | | | | |
| Mass | Crncy.| Mol |
Length Time Temp. Lum.Intensity
this will be sufficient for demonstrating the problem:
Quantity[_1]
^
|
Length
As soon as the type needs to be inferred, the trouble starts.
Consider this example (also have a look at the code from UnitsTest.scala):
val length: Quantity[_1] = m(5)
val area: Quantity[_2] = length * length // (1) Works
val dist: Quantity[_1] = area / length // (2) Doesn't work!
I get an error in the last line saying:
type mismatch;
found :
scalax.units.Units.Quantity[
scalax.units.Subtractables.-[
scalax.units.Integers._2,
scalax.units.Integers._1
]
]
required:
scalax.units.Units.Quantity[
scalax.units.Integers._1
]
It looks like the compiler can't figure out that the type at hand is equal to Quantity[_1]
when "substracting a dimension", e. g. going from area to dist like in (1)
:
Quantity[_2 - _1] <<not equal to>> Quantity[_1]
The confusing thing is that it works when "adding a dimension" e. g. going from length to area like in (2)
:
Quantity[_1 + _1] <<equal to>> Quantity[_2]
(Sorry for not pasting the whole code here, it is just too much. I tried to minimize my example, but I failed. That's why I'm just linking to it.)
Type Sub
from Subtractable
is missing in the MInt
trait. A simple definition to make it work would be to perform a negative addition when you want to subtract a type in MSucc
and MNeg
.
sealed trait MInt extends Visitable[IntVisitor] with Addable with Subtractable {
type AddType = MInt
type SubType = MInt
type Add[I <: MInt] <: MInt
type Sub[I <: MInt] <: MInt
type Neg <: MInt
type Succ <: MInt
type Pre <: MInt
}
final class _0 extends Nat {
type Add[I <: MInt] = I
type Sub[I <: MInt] = I#Neg
type AcceptNatVisitor[V <: NatVisitor] = V#Visit0
type Neg = _0
type Succ = MSucc[_0]
type Pre = Succ#Neg
}
final class MSucc[P <: Nat] extends Pos {
type This = MSucc[P]
type Add[N <: MInt] = P#Add[N]#Succ
type Sub[N <: MInt] = Add[N#Neg]
type AcceptNatVisitor[V <: NatVisitor] = V#VisitSucc[P]
type Neg = MNeg[This]
type Pre = P
type Succ = MSucc[This]
}
final class MNeg[P <: Pos] extends MInt {
type Add[N <: MInt] = P#Add[N#Neg]#Neg
type Sub[N <: MInt] = Add[N#Neg]
type Accept[V <: IntVisitor] = V#VisitNeg[P]
type Neg = P
type Succ = P#Pre#Neg
type Pre = P#Succ#Neg
}
One more thing, the /
method in Quantity
should divide its parameters and not multiply them!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With