"No default Typeable for parametrized type" 使用 Shapeless 2.1.0-RC2
"No default Typeable for parametrized type" using Shapeless 2.1.0-RC2
我试图使用 Shapeless Typeable 使对 Java 库的访问更加类型安全,但 运行 成为障碍。我不确定我是否在滥用该库,必须手动提供一个 type-class 实例,或者是否有其他问题。
此代码演示了我的问题的简化演示..
import shapeless._
import syntax.typeable._
def gaugeOpt(name: String): Option[Gauge[Double]] = {
return registry.getGauges.get(name).cast[Gauge[Double]]
}
..使用 Shapeless-2.1.0-RC2 和 Scala 2.11.5 导致此错误:
No default Typeable for parametrized type com.codahale.metrics.Gauge[Double]
显示的库并不重要;只是对在我的 Scala 代码中使用它们时使 Java 库更加类型安全的一般模式感兴趣。
解法:
根据已接受答案的建议,我编写了以下类型 class 实例:
implicit def gaugeTypeable[T](implicit castT: Typeable[T]): Typeable[Gauge[T]] =
new Typeable[Gauge[T]] {
def cast(t: Any): Option[Gauge[T]] = {
if(t == null) None
else if(t.isInstanceOf[Gauge[_]]) {
castT.cast(t.asInstanceOf[Gauge[_]].getValue) match {
case None => None
case _ => Some(t.asInstanceOf[Gauge[T]])
}
} else None
}
}
唯一需要注意的是,我必须访问仪表值访问器才能恢复已擦除的类型。
没有参数化的类型有一个默认的 Typeable
实例,因为您可以通过检查它们的运行时间 class 来安全地(大概)转换它们。但是由于泛型在运行时被删除,这对于参数化类型来说是不安全的; t.getClass()
可能 return Gauge.class
,但这并不能保证 t
是 Gauge[Double]
而不是 Gauge[Int]
.
您需要手动提供类型class实例:
implicit def gaugeTypeable[A](implicit innerTypeable: Typeable[A]) =
new Typeable[Gauge[A]] {
def cast(t: Any): Option[Gauge[A]] = ...
//confirm whether t is really a Gauge[A]
//probably making use of innerTypeable to check the
//"inner" value
}
我试图使用 Shapeless Typeable 使对 Java 库的访问更加类型安全,但 运行 成为障碍。我不确定我是否在滥用该库,必须手动提供一个 type-class 实例,或者是否有其他问题。
此代码演示了我的问题的简化演示..
import shapeless._
import syntax.typeable._
def gaugeOpt(name: String): Option[Gauge[Double]] = {
return registry.getGauges.get(name).cast[Gauge[Double]]
}
..使用 Shapeless-2.1.0-RC2 和 Scala 2.11.5 导致此错误:
No default Typeable for parametrized type com.codahale.metrics.Gauge[Double]
显示的库并不重要;只是对在我的 Scala 代码中使用它们时使 Java 库更加类型安全的一般模式感兴趣。
解法:
根据已接受答案的建议,我编写了以下类型 class 实例:
implicit def gaugeTypeable[T](implicit castT: Typeable[T]): Typeable[Gauge[T]] =
new Typeable[Gauge[T]] {
def cast(t: Any): Option[Gauge[T]] = {
if(t == null) None
else if(t.isInstanceOf[Gauge[_]]) {
castT.cast(t.asInstanceOf[Gauge[_]].getValue) match {
case None => None
case _ => Some(t.asInstanceOf[Gauge[T]])
}
} else None
}
}
唯一需要注意的是,我必须访问仪表值访问器才能恢复已擦除的类型。
没有参数化的类型有一个默认的 Typeable
实例,因为您可以通过检查它们的运行时间 class 来安全地(大概)转换它们。但是由于泛型在运行时被删除,这对于参数化类型来说是不安全的; t.getClass()
可能 return Gauge.class
,但这并不能保证 t
是 Gauge[Double]
而不是 Gauge[Int]
.
您需要手动提供类型class实例:
implicit def gaugeTypeable[A](implicit innerTypeable: Typeable[A]) =
new Typeable[Gauge[A]] {
def cast(t: Any): Option[Gauge[A]] = ...
//confirm whether t is really a Gauge[A]
//probably making use of innerTypeable to check the
//"inner" value
}