2

我有一个带有隐式 TypeTag 参数的反射函数:

def fromOptionFn[R: TypeTag](self: Int => Option[R]): Wrapper[R] = {
println(TypeTag[R])
...
}

哪个由于未知原因不起作用(请参阅如何使 Scala 类型推断功能强大到足以发现泛型类型参数?):

> fromOptionFn2(v => Some(" + _))
> typeTag(Any)

我推测它是由 Option[R] 推断 R 引起的,所以我对其进行了一些改进:

def fromOptionFn[R, Opt <: Option[R]: TypeTag](self: Int => Opt): Wrapper[R] = {
println(typeTag[Opt])
...
}

这次更糟,甚至没有编译,错误清楚地推断出 scala 不够聪明,无法分析类型:

> fromOptionFn2(v => Some(" + _))
Error: inferred type arguments [Nothing,Option[String]] do not conform to method fromOptionFn's type parameter bounds [R,Opt <: Option[R]]

那么如何临时规避这个编译问题呢?(当然我可以在 Lightbend 问题跟踪器上报告它,但它太慢了)

附录:这个问题本身是一个尝试规避如何使 Scala 类型推断功能强大到足以发现泛型类型参数?,这可能不会被修复。在我的情况下,我不介意获得类型 R 或 Option[R] 的 TypeTag,无论工作如何。

4

1 回答 1

1

这不是一种改进,恰恰相反,Scala 类型推断根本不支持Opt先推断并R从那里得到:相反,它推断Nothing是因为R它不是任何参数类型的一部分(并且返回类型是未知的)。

您可以通过在每次调用中显式指定类型参数来规避它:fromOptionFn2[String, Option[String]](...). 我认为,在这种特定情况下,给出预期的类型也应该起作用:fromOptionFn2(...): Wrapper[String]. 然而,一个更好的主意是不要像[R, Opt <: Option[R]]一开始那样使用类型参数签名。

于 2016-06-18T21:23:31.640 回答