【发布时间】:2017-03-16 11:04:01
【问题描述】:
我有这个代码:
trait Context {
implicit val e: Encoder
trait Encoder {
def write(): Unit = {
println("Test")
}
}
}
trait AsyncEncoders {
this: Context =>
class AsyncEncoder extends Encoder {
}
implicit val e = new AsyncEncoder()
}
class ConcreteContext extends Context with AsyncEncoders {
}
当我这样使用时(案例1):
object Main extends App {
implicit val c = new ConcreteContext()
import c._
implicitly[Encoder].write()
}
然后它编译并打印Test。
但是当我尝试在单例对象中调用相同的代码时(case 2):
object TestObject {
def apply()(implicit c: ConcreteContext): Unit = {
import c._
implicitly[Encoder].write()
}
}
object Main extends App {
implicit val c = new ConcreteContext()
TestObject()
}
编译失败:
path/to/Main.scala:29:找不到参数 e 的隐式值:c.Encoder 隐式[c.Encoder].write()
如果我改变(案例 3):
implicit val e = new AsyncEncoder()
到
implicit val e: Encoder = new AsyncEncoder()
然后它按预期编译和运行。
但由于某种原因,这对我来说是不可接受的。
上述情况为什么编译失败?
【问题讨论】:
-
我没有答案给你,但为了清楚起见,你在这里与 Scala 作斗争。如果您将
Encoder实现为类型类而不是依赖于路径的类型,事情会变得更加顺利,类型推断路径也会有更多的文档说明。 -
似乎对以隐式参数形式出现的依赖于路径的类型有问题。
-
我不是 100% 确定这里出了什么问题,但这确实可以在 Scala 2.12.0 中编译。
-
@Jasper-M 是的,它确实在 Scala 2.12.0 中编译。谢谢!所以这是 Scala 2.11.* 编译器问题。
-
嗯,你的
Encoder特征是 SAM,他们在 2.12 中改变了对 SAM 的处理。不确定这是否是它在 2.12 中编译并在 2.11 中出错的根本原因,但这是我的第一个直觉。