2016-10-24 13 views
5

Poniższy kod skompilowany kończy się niepowodzeniem, ale został przekazany, jeśli usunięto adnotację specialized w metodzie .Czy to błąd specjalisty scala?

Scala wersja kodu biegacz 2.12.0-RC2 - Prawa autorskie 2002-2016, LAMP/EPFL i Lightbend, Inc.

abstract class Op[@specialized Left, @specialized Right] { 
    @specialized 
    type Result 

    def r: Numeric[Result] 
    def times(left: Left, right: Right): Result 
} 


object Op { 

    implicit object IntDoubleOp extends Op[Int, Double] { 
    type Result = Double 
    val r = implicitly[Numeric[Double]] 
    def times(left: Int, right: Double): Double = left * right 
    } 
} 


object calc { 

    def dot[@specialized Left, @specialized Right](xs: Array[Left], ys: Array[Right]) 
      (implicit op: Op[Left, Right]): op.Result = { 
    var total = op.r.zero 
    var index = xs.length 
    while(index > 0) { 
     index -= 1 
     total = op.r.plus(total, op.times(xs(index), ys(index))) 
    } 
    total 
    } 
} 

test.scala:31: error: type mismatch; 
found : op.Result 
required: op.Result 
    total 
    ^
one error found 

Oto kolejny spróbować bez powodzenia:

//cat Ops.scala 
import scala.{ specialized => sp } 

trait OpsResult { 
    type N 
} 

trait SymOps extends OpsResult { 
    @sp override type N 
    def zero: N 
    def plus(left: N, right: N): N 
} 

trait AsyOps[@sp L, @sp R] extends OpsResult { 
    @sp override type N 
    def times(left: L, right: R): N 
} 

trait MixOps[@sp L, @sp R] extends AsyOps[L, R] with SymOps 

object MixOps { 
    trait DoubleOps extends SymOps { 
    override type N = Double 
    def zero: Double = 0.0 
    override def plus(left: Double, right: Double): Double = left + right 
    } 
    trait IntDoubleOps extends AsyOps[Int, Double] { 
    override type N = Double 
    override def times(left: Int, right: Double): Double = left * right 
    } 

    implicit object MixIntDouble extends IntDoubleOps with DoubleOps 
} 

object Test { 
    def dot[@sp L, @sp R](xs: Array[L], ys: Array[R]) 
     (implicit op: MixOps[L, R]): op.N = { 
    op.zero 
    } 
} 

$ scalac Ops.scala 
Ops.scala:36: error: type mismatch; 
found : op.N 
required: op.N 
    op.zero 
    ^
one error found 

Odpowiedz

5

To jest błąd (powtarza się również w 2.11.x). Skontaktowałem się z chłopakami z LightBend i jest to z pewnością dziwactwo z generowaniem kodu dla specjalizacji i typów zależnych od ścieżki. Mam zmniejszyła go do smukłej powielać:

trait M[@specialized T] { 
    type Res 
    def res: Res 
} 

object Test { 
    def m[@specialized T](op: M[T]): op.Res = op.res 
} 

Symbole op będą zsynchronizowane i nie będzie kompilować, jak widać w kodzie. @AdriaanMoors has opened a bug dotyczące tego problemu.

Adriaan zwrócił mi także uwagę na this blog post autorstwa Aleksandara Prokopeca, który wskazuje na pewne dziwactwa w generowaniu kodu @specilization.