【问题标题】:Using ClassTag with Variance使用具有方差的 ClassTag
【发布时间】:2015-12-07 09:23:56
【问题描述】:

我有一个变压器,它只是一个 scala 函数,但需要 ClassTag 才能与旧代码互操作:

trait Transformer[F, T] extends (F => T) {
  implicit def cF: ClassTag[F]
  implicit def cT: ClassTag[T]

  /**
   * Append another transformer to this transformer
   */
  def >=>[U: ClassTag](f: Transformer[T, U]): Transformer[F, U] = Transformer(this andThen f)
}

/** Helper to view a function as a transformer */
object Transformer {
  def apply[F: ClassTag, T: ClassTag](f: F => T): Transformer[F, T] = new AbstractTransformer[F, T] {
    override def apply(x: F): T = f(x)
  }
}

abstract class AbstractTransformer[F, T](implicit override val cF: ClassTag[F], override val cT: ClassTag[T]) extends Transformer[F, T]

但是,我希望 TF 与 scala 有相同的差异 Function1 是

trait Transformer[-F, +T] extends (F => T)

然而这会导致

逆变类型 F 出现在类型中的不变位置 => cF Transformer.scala方法的scala.reflect.ClassTag[F]

协变类型 T 出现在类型中的不变位置 => cT Transformer.scala方法的scala.reflect.ClassTag[T]

我能以某种方式解决这个问题吗?

【问题讨论】:

    标签: scala


    【解决方案1】:
    import scala.annotation.unchecked.uncheckedVariance
    ...
    implicit def cF: ClassTag[F @uncheckedVariance]
    implicit def cT: ClassTag[T @uncheckedVariance]
    

    但是,您需要小心使用它:错误是有原因的!例如,考虑

    val t: Transformer[String, Object] = ...
    val t1: Transformer[Object, String] = t // legal by variance
    val c1 = t1.cF // the compiler thinks it's a ClassTag[Object], but really it's the ClassTag for String
    val c2 = t1.cT // vice versa
    

    【讨论】:

      猜你喜欢
      • 2016-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      相关资源
      最近更新 更多