如何使 Scala 类型推断足够强大以发现泛型类型参数?
How to make Scala type inference powerful enough to discover generic type parameter?
假设我定义了一个采用隐式 TypeTag 的函数:
def andOptionFn[A: TypeTag](g: Int => Option[A]) = {
val ttg = ScalaReflection.universe.typeTag[A]
println(ttg)
...
}
并称它为:
andOptionFn{
v =>
Some(v)
}
我希望 scala 类型推断得到正确的类型 TypeTag(Option(Int)),但我却得到:
TypeTag(Option(Any)) (not even a higher kind)
为什么Scala无法在编译时自动推断?需要做哪些工作来改进它?
正确的结果是 TypeTag[Int]
,Scala 确实打印了它:http://scastie.org/20273(在将 ScalaReflection
替换为 scala.reflect.runtime
之后;如果 ScalaReflection
是你的自己 class,那是你应该寻找问题的地方)。
编辑:http://scastie.org/20293 不是错误,它是类型推断,其行为完全符合设计。调用 Seq.apply[Option[_]]
为每个参数提供 Option[_]
的预期类型。当
andOptionFn {
v =>
if (v > 1) Some(v)
else None
}
被类型检查 使用此预期类型 ,推断的 R
当然是 Any
.
编辑 2:阅读 http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#local-type-inference 更仔细一点,它似乎确实应该推断出 Int
,但我不确定。我的想法是 Option[_]
被简化为 Option[Any]
(因为 Option
是协变的),在这种情况下 Any
当然应该被推断出来。但是 http://scastie.org/20293 和 http://scastie.org/20295 应该表现相同,所以至少有一个错误(我认为):)
假设我定义了一个采用隐式 TypeTag 的函数:
def andOptionFn[A: TypeTag](g: Int => Option[A]) = {
val ttg = ScalaReflection.universe.typeTag[A]
println(ttg)
...
}
并称它为:
andOptionFn{
v =>
Some(v)
}
我希望 scala 类型推断得到正确的类型 TypeTag(Option(Int)),但我却得到:
TypeTag(Option(Any)) (not even a higher kind)
为什么Scala无法在编译时自动推断?需要做哪些工作来改进它?
正确的结果是 TypeTag[Int]
,Scala 确实打印了它:http://scastie.org/20273(在将 ScalaReflection
替换为 scala.reflect.runtime
之后;如果 ScalaReflection
是你的自己 class,那是你应该寻找问题的地方)。
编辑:http://scastie.org/20293 不是错误,它是类型推断,其行为完全符合设计。调用 Seq.apply[Option[_]]
为每个参数提供 Option[_]
的预期类型。当
andOptionFn {
v =>
if (v > 1) Some(v)
else None
}
被类型检查 使用此预期类型 ,推断的 R
当然是 Any
.
编辑 2:阅读 http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#local-type-inference 更仔细一点,它似乎确实应该推断出 Int
,但我不确定。我的想法是 Option[_]
被简化为 Option[Any]
(因为 Option
是协变的),在这种情况下 Any
当然应该被推断出来。但是 http://scastie.org/20293 和 http://scastie.org/20295 应该表现相同,所以至少有一个错误(我认为):)