我试图理解为什么隐式转换在一种情况下有效,而在另一种情况下不起作用。下面是一个示例:
case class Wrapper[T](wrapped: T)
trait Wrapping { implicit def wrapIt[T](x: Option[T]) = x.map(Wrapper(_))
class NotWorking extends Wrapping { def foo: Option[Wrapper[String]] = Some("foo") }
class Working extends Wrapping {
def foo: Option[Wrapper[String]] = {
val why = Some("foo")
why
}
}基本上,我有一个从Option[T]到Option[Wrapper[T]]的隐式转换,并且正在尝试定义一个函数,该函数返回一个隐式包装的可选字符串。
问题是,为什么当我尝试直接返回Option[String] (上面的NotWorking)时,我得到一个错误(found : String("foo") required: Wrapper[String]),如果我在返回结果之前将结果赋给val,这个错误就会消失。
怎么回事?
发布于 2017-05-15 22:38:49
我不知道这是不是故意的,或者会被认为是一个bug,但我认为这是正在发生的事情。
在def foo: Option[Wrapper[String]] = Some("foo")中,编译器会将提供给Some( )的参数的预期类型设置为Wrapper[String]。然后,它看到您提供了一个不是预期的String,因此它查找隐式转换String => Wrapper[String],但找不到,因此失败。
为什么它需要预期的类型,而不只是输入Some("foo")作为Some[String],然后尝试找到一个转换?因为scalac希望能够对以下代码进行类型检查:
case class Invariant[T](t: T)
val a: Invariant[Any] = Invariant("s")为了让这段代码正常工作,编译器不能只键入Invariant("s")作为Invariant[String],因为这样编译就会失败,因为Invariant[String]不是Invariant[Any]的子类型。编译器需要将预期的"s"类型设置为Any,这样它就可以在为时过晚之前看到"s"是Any的一个实例。
为了让这段代码和你的代码都能正确工作,我认为编译器需要某种回溯逻辑,而这似乎是没有的,也许是有很好的理由的。
您的Working代码之所以能够正常工作,是因为这种类型推断不会跨越多行。类似地,val a: Invariant[Any] = {val why = Invariant("s"); why}不能编译。
https://stackoverflow.com/questions/43981576
复制相似问题