2011-10-21 9 views
6

He encontrado un problema al trabajar con la funcionalidad de Unidades de medida en metascala, definida en el archivo Units.scala.Error de tipo de inferencia/comprobación de tipo al utilizar cálculos de tipo de nivel

Para el resto de esta pregunta, utilizaré un esquema simplificado, con solo un tipo de Unidad, longitud.

Entonces, ¿dónde en realidad un tipo se parece a

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

esto será suficiente para demostrar el problema:

Quantity[_1] 
     ^
      | 
     Length 

Tan pronto como el tipo necesita ser inferida, empiezan los problemas.

Considere este ejemplo (también echar un vistazo al código de 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! 

consigo un error en la última línea que dice:

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 
    ] 

Parece que el compilador puede' t averigüe que el tipo en cuestión es igual a Quantity[_1] al "restar una dimensión", e. gramo. ir de área a dist como en (1):

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

Lo confuso es que funciona cuando "añadiendo una dimensión" e. gramo. Pasar de longitud de área como en (2):.

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

(Lo siento por no pegar todo el código aquí, es simplemente demasiado traté de minimizar mi ejemplo, pero fallé Es por eso que estoy vinculación. a él.)

Respuesta

2

Tipo Sub de Subtractable falta en el rasgo MInt. Una definición simple para hacer que funcione sería realizar una adición negativa cuando desee restar un tipo en MSucc y 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 
} 

Una cosa más, el método / en Quantity deben dividir sus parámetros y no multiplicarlos!

+0

Sí, esta es la solución. He asignado las dos correcciones al repositorio de MetaScala. –

Cuestiones relacionadas