Type / type input fails when using type level calculations

I encountered a problem while working with the Units of Measurements functionality in metascala defined in the Units.scala file.

For the remainder of this question, I will use a simplified scheme with one type of Unit, length.

So, where the type actually looks like

Quantity[_1, _0, _0, _0, _0, _0, _0] ^ ^ ^ ^ ^ ^ ^ | | | | | | | | Mass | Crncy.| Mol | Length Time Temp. Lum.Intensity 

this will be enough to demonstrate the problem:

 Quantity[_1] ^ | Length 

As soon as the type needs to be inferred, the problem begins.

Consider this example (also see UnitsTest.scala code):

 val length: Quantity[_1] = m(5) val area: Quantity[_2] = length * length // (1) Works val dist: Quantity[_1] = area / length // (2) Doesn't work! 

An error appears in the last line:

 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 seems that the compiler cannot understand that the type at hand is equal to Quantity[_1] , when the “extrusion dimension”, e. d. the transition from region to dist, as in (1) :

 Quantity[_2 - _1] <<not equal to>> Quantity[_1] 

The fallacy is that it works when “adding dimension” e. d. from length to region, as in (2) :

 Quantity[_1 + _1] <<equal to>> Quantity[_2] 

(Sorry for not inserting all the code here, this is too much. I tried to minimize my example, but I failed. That's why I just get in touch with it.)

+6
source share
1 answer

The Sub type of the Subtractable missing in the MInt . A simple definition to make it work would be to perform a negative addition if you want to subtract the 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!

+2
source

Source: https://habr.com/ru/post/899825/


All Articles