为什么scala';s隐式查找忽略嵌套类的伴随对象
我在玩下面的代码:为什么scala';s隐式查找忽略嵌套类的伴随对象,scala,nested,implicit,companion-object,path-dependent-type,Scala,Nested,Implicit,Companion Object,Path Dependent Type,我在玩下面的代码: class A class B class C trait Codecs[L] { case class Codec[R](val code: L => R, val decode: R => L) object Codec def code[R](foo: L)(implicit codec: Codec[R]): R = codec.code(foo) def decode[R](bar: R)(implicit codec
class A
class B
class C
trait Codecs[L] {
case class Codec[R](val code: L => R, val decode: R => L)
object Codec
def code[R](foo: L)(implicit codec: Codec[R]): R = codec.code(foo)
def decode[R](bar: R)(implicit codec: Codec[R]): L = codec.decode(bar)
}
object Codecs {
implicit object ACodecs extends Codecs[A] {
object Codec {
implicit val ab: Codec[B] = new Codec(_ => new B, _ => new A)
implicit val ac: Codec[C] = new Codec(_ => new C, _ => new A)
}
}
}
object test extends App {
val codecs = implicitly[Codecs[A]]
codecs.code[B](new A)
}
它不会编译,因为编译器无法找到类型为Codecs.Codec[B]
的隐式值。
据我所知,两个值ab
和ac
的类型是Acodecs.Codec[\u]
(或类似的类型),这并不是编译器想要的。我还知道,将case类Codec[\u]
及其同伴移动到trait之外可以解决问题(在使其接受2个类型参数之后)。如果需要隐式值,编译器应该在隐式作用域中包含所需类型的伴随对象。我的问题是:
trait
的两个方法的签名(理想情况下更改隐式参数的类型签名)以使此编译?如何从traitCodecs[\u]
内部引用类型Acodecs.Codec[\u]
问题是您的类型绑定到特定实例,因为它是一个内部类。编译器不知道
隐式[Codecs[A]
给出的实例与下一行隐式找到的实例完全相同。例如,如果显式传递它:
codecs.code[B](new A)(Codecs.ACodecs.Codec.ab)
您将收到以下错误消息:
type mismatch;
found : Codecs.ACodecs.Codec[B]
required: codecs.Codec[B]
因此,它认为封闭实例可能不同,类型也不同
我从来没有真正见过这种特定类型的隐式嵌套,即隐式类型类,其中包含路径依赖的隐式类型类。所以我怀疑是否有一种模式来处理它,事实上,我会建议反对它。这似乎太复杂了。以下是我个人如何处理这个案件:
case class Codec[L, R](val code: L => R, val decode: R => L)
trait Codecs[L] {
type LocalCodec[R] = Codec[L, R]
def code[R](foo: L)(implicit codec: LocalCodec[R]): R = codec.code(foo)
def decode[R](bar: R)(implicit codec: LocalCodec[R]): L = codec.decode(bar)
}
object Codecs {
implicit object ACodecs extends Codecs[A] {
implicit val ab: LocalCodec[B] = new LocalCodec(_ => new B, _ => new A)
implicit val ac: LocalCodec[C] = new LocalCodec(_ => new C, _ => new A)
}
}
object test extends App {
import Codecs.ACodecs._
val codecs = implicitly[Codecs[A]]
codecs.code[B](new A)
}
您仍然可以使用“半窄化”类型,但它只是一个类型别名,因此没有路径依赖性问题。谢谢您的回答。导致我产生这段代码的原因是我想避免调用站点导入。实际上,嵌套类没有(不会)同伴,我没有类型类嵌套。