2016-10-24 37 views
5

Aşağıdaki kod derlenmiş başarısız olur, ancak ek açıklamasını dot yönteminde kaldırırsam iletilir.Bu scala'nın uzmanı bir böcek mi?

Scala kod koşucu versiyonu 2.12.0-RC2 - Telif Hakkı 2002-2016, LAMBA/epfl ve 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 
İşte

başka hiçbir şans ile deneyin:

//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 

cevap

5

Bu bir hatadır (ayrıca 2.11.x üzerinde yeniden üretir). LightBend'deki adamlarla iletişim kurdum ve bu kesinlikle uzmanlık ve yola bağlı türler için kod oluşturma ile bir tuhaflık. Ben ince çoğaltmak aşağı daralmış ettik: op için

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

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

semboller senkronize edilmemiş olacak ve kodunuzda gördüğünüz gibi derlemek olmaz. Bu sorunla ilgili @AdriaanMoors has opened a bug. Adriaan ayrıca, @specilization kod üretimindeki bazı tuhaf noktalara işaret eden Aleksandar Prokopec'in this blog post numaralı telefonuna da işaret etmiştir.