units icon indicating copy to clipboard operation
units copied to clipboard

DoubleU[/[O,I]#Mul[I]] not being treated as Double[O]

Open gbeaty opened this issue 10 years ago • 2 comments

def linear[I <: MUnit,O <: MUnit](n: String, offset: DoubleU[O], coef: DoubleU[O / I]) =
  Sensor.Invertible[I,O](n, i => offset + coef * i, o => (o - offset) / coef)

Produces:

[error]  overloaded method value + with alternatives:
[error]   (i: DoubleU[O])DoubleU[O] <and>
[error]   (i: IntU[O])DoubleU[O]
[error]  cannot be applied to (DoubleU[/[O,I]#Mul[I]])
[error]       Sensor.Invertible[I,O](n, i => offset + coef * i, o => (o - offset) / coef)
[error]                                             ^

Is that sort of type-arithmetic even possible in Scala? I'm guessing not, but had to ask.

gbeaty avatar Aug 09 '14 00:08 gbeaty

No, sadly Scala is not that smart. Maybe type macros could help, but I don't think they're done yet, and also I'm not a macro guru.

You can either:

  • cast explicitly, losing type safety

  • add (impicit ev: (O/I)#Mul[I] =:= O) to the parameters: it's ugly, it needs you to get the aforementioned compilation error first, and won't work in any more complicated case

  • use explicit polymorphism using Systems, but that's a lot of work:

    type Input = DefineType[_I]
    type Output = DefineType[_O]
    def linear(n: String, offset: DoubleU[Output], coef: DoubleU[Output / Input]) = .......
    
    (...)
    
    val X = System2[Input, second, Output, milimetre]
    val X(result) = linear("string", X(offset), X(coeff))    //result is in mm
    

https://github.com/KarolS/units/blob/master/doc/POLYMORPHISM.md

KarolS avatar Aug 10 '14 21:08 KarolS

You could also normalize the result type multiplication based on the input parameter types. That would require some implicits, depend path and would make the code much more complicated. It would be also necessary to think about what is normalized representation of units should look like.

Jentsch avatar Sep 02 '16 00:09 Jentsch