【问题标题】:Is this a bug of scala's specialized?这是scala专业的bug吗?
【发布时间】:2017-03-05 23:35:04
【问题描述】:

以下代码编译失败,但如果我删除方法 dot 中的 specialized 注释,则它通过了。

Scala 代码运行程序版本 2.12.0-RC2 -- 版权所有 2002-2016,LAMP/EPFL 和 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

这是另一个没有运气的尝试:

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

【问题讨论】:

    标签: scala template-specialization


    【解决方案1】:

    这是一个错误(也在 2.11.x 上重现)。我已经联系了 LightBend 的人,这对于专业化和路径相关类型的代码生成绝对是一个怪癖。我已经把它缩小到一个苗条的复制品:

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

    op 的符号将不同步,并且不会像您在代码中看到的那样编译。 @AdriaanMoors has opened a bug 关于这个问题。

    Adriaan 还向我指出了 Aleksandar Prokopec 的 this blog post,它指出了 @specilization 代码生成中的一些怪癖。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      • 2018-09-08
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 2011-04-07
      相关资源
      最近更新 更多