我有一个函数,可以使用无类型将 Scala 中的Something[Any]
转换为Something[X]
:
import shapeless._
import shapeless.syntax.typeable._
def doCast[T: Typeable](v: Vector[Any]): T = v.cast[T].get
现在我想按索引访问列表:
val a = Vector[Any](1,2,3);
println(doCast[Vector[Int]](a)(1))
但这会引发一个异常:
/path/to/Test.scala:12: error: type mismatch;
found : Int(1)
required: shapeless.Typeable[Vector[Any]]
println(doCast[Vector[Int]](a)(1))
^
one error found
但是,如果我先将此结果分配给变量,它会正确打印2
:
val a = Vector[Any](1,2,3);
val c = doCast[Vector[Int]](a)
println(c(1))
同样,如果我使用asInstanceOf
转换结果,它可以正常工作:
val a = Vector[Any](1,2,3);
println(doCast[Vector[Int]](a).asInstanceOf[Vector[Int]](1));
我可以创建一个返回可索引结果的函数吗?
我尝试这样做,但我的尝试没有奏效:
def doCast2[T](v: Vector[Any]): T = doCast(v).asInstanceOf[T]
给出此错误:
/path/to/Test.scala:10: error: diverging implicit expansion for type shapeless.Typeable[T]
starting with method inrTypeable in object Typeable
def doCast2[T](v: Vector[Any]): T = doCast(v).asInstanceOf[T]
^
one error found
和
def doCast2[T](v: Vector[Any]): T = doCast[T](v).asInstanceOf[T]
给出此错误:
/path/to/Test.scala:10: error:
class type required but T found
def doCast2[T](v: Vector[Any]): T = doCast[T](v).asInstanceOf[T]
^
one error found
问题似乎是脱糖后doCast的实际签名是从以下转换而来的:
def doCast[T: Typeable](v: Vector[Any]): T
自
def doCast[T](v: Vector[Any])(implicit ev1: Typeable[T]): T
所以当这样称呼它时
doCast[Vector[Int]](a)(1)
您正在 Typeable[T] 的位置传递 1。
最简单的解决方案是直接指定参数:
doCast[Vector[Int]](a)(implicitly)(1)
或者在doCast之后对向量使用单独的val