Scala 为什么提取和分配单个元组值会导致递归隐式搜索?

Scala 为什么提取和分配单个元组值会导致递归隐式搜索?,scala,implicits,Scala,Implicits,以下是产生此错误的代码: [info] Compiling 1 Scala source to /tmp/test/target/scala-2.11/classes... [error] /tmp/test/test.scala:4: recursive value x$1 needs type [error] final implicit val (enc, dec) = { [error] ^ [error] one error fo

以下是产生此错误的代码:

[info] Compiling 1 Scala source to /tmp/test/target/scala-2.11/classes...
[error] /tmp/test/test.scala:4: recursive value x$1 needs type
[error]     final implicit val (enc, dec) = {
[error]                         ^
[error] one error found
build.sbt

斯卡拉测试

试图编译此文件将导致以下错误:

[info] Compiling 1 Scala source to /tmp/test/target/scala-2.11/classes...
[error] /tmp/test/test.scala:4: recursive value x$1 needs type
[error]     final implicit val (enc, dec) = {
[error]                         ^
[error] one error found
在完全调试模式打开的情况下,我可以看到它正在尝试解析
==
,编译器正在查看当前隐式,以确定是否有匹配项。由于
(enc,dec)
是隐式的,它似乎也使用它们,因此它尝试键入它们,导致编译器抱怨这种隐式递归

|    |    |    |    |    |-- "x".$eq$eq$eq("y") EXPRmode-POLYmode-QUALmode (silent: value x$1 in package) 
|    |    |    |    |    |    |-- "x".$eq$eq$eq BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value x$1 in package) 
|    |    |    |    |    |    |    |-- "x" EXPRmode-POLYmode-QUALmode (silent: value x$1 in package) 
|    |    |    |    |    |    |    |    \-> String("x")
|    |    |    |    |    |    |    |-- x$1._1 EXPRmode (site: value enc  in package) 
|    |    |    |    |    |    |    |    |-- x$1 EXPRmode-POLYmode-QUALmode (site: value enc  in package) 
|    |    |    |    |    |    |    |    |    caught scala.reflect.internal.Symbols$CyclicReference: illegal cyclic reference involving value x$1: while typing x$1
[error] /tmp/test/test.scala:4: recursive value x$1 needs type
[error]     final implicit val (enc, dec) = {
[error]                         ^
|    |    |    |    |    |    |    |    |    \-> <error>
|    |    |    |    |    |    |    |    \-> <error>
|    |    |    |    |    |    |    |-- x$1._2 EXPRmode (site: value dec  in package) 
|    |    |    |    |    |    |    |    |-- x$1 EXPRmode-POLYmode-QUALmode (site: value dec  in package) 
|    |    |    |    |    |    |    |    |    \-> <error>
|    |    |    |    |    |    |    |    \-> <error>
|    |    |    |    |    |    |    |-- SafeEquals BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value x$1 in package) implicits disabled
|    |    |    |    |    |    |    |    |-- ai.x.safe.`package` EXPRmode-POLYmode-QUALmode (silent: value x$1 in package) implicits disabled
|    |    |    |    |    |    |    |    |    \-> ai.x.safe.type
|    |    |    |    |    |    |    |    \-> ai.x.safe.SafeEquals.type <and> [T](l: T)ai.x.safe.SafeEquals[T]
|    |    |    |    |    |    |    solving for (T: ?T)
|    |    |    |    |    |    |    solving for (T: ?T)
|    |    |    |    |    |    |    solving for (T: ?T)
|    |    |    |    |    |    |    [adapt] SafeEquals adapted to [T](l: T)ai.x.safe.package.SafeEquals[T] based on pt String("x") => ?{def ===: ?}
|    |    |    |    |    |    |    |-- [T](l: T)ai.x.safe.package.SafeEquals[T] EXPRmode-POLYmode-QUALmode (silent: value x$1 in package) 
|    |    |    |    |    |    |    |    \-> ai.x.safe.package.SafeEquals[String]
|    |    |    |    |    |    |    |-- ai.x.safe.`package`.SafeEquals[String]("x").$eq$eq$eq BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value x$1 in package) 
|    |    |    |    |    |    |    |    \-> (r: String)Boolean
|    |    |    |    |    |    |    \-> (r: String)Boolean
|    |    |    |    |    |    |-- "y" : pt=String BYVALmode-EXPRmode (silent: value x$1 in package) 
|    |    |    |    |    |    |    \-> String("y")
|    |    |    |    |    |    \-> Boolean
由于在定义
{}
的主体时隐式不存在,因此当从
SafeEquals
定位
===
可以应用于
字符串并使代码工作时,隐式不会干扰编译器的隐式搜索。现在我对这一点没有什么问题,因为它确实有意义,因为可以定义懒惰的递归序列化程序和其他隐式的东西,它们可以毫无问题地使用它们自己。因此,编译器当然应该查看隐式的,它被定义为一个可能的应用程序,以使某些东西工作

但对我来说,奇怪的是,如果在赋值过程中不直接提取元组,这种方法是有效的:

final implicit val tuple = {
    ("x" === "y") -> 0
}

显然,这不是我想要做的,因为我希望元组中的两个东西都是隐式的(在我的真实案例中,它是来自circe的编码器/解码器对)。但对我来说很奇怪的是,对Tuple2使用提取器(我认为是提取器)会导致搜索隐式的编译器错误。有谁能告诉我为什么会发生这种情况,或者是什么导致了这种行为?我想知道更多关于调试输出中看到的内容。为什么解析元组中每个单独事物的类型会导致编译器错误,但解析整个元组的类型不会导致任何问题?

如果将显式类型添加到
enc
dec
,会发生什么情况
val(enc:Boolean,dec:Int)=……
@BobDalgleish如果我显式地在元组中键入元素,那么它会编译。我对编译它不太感兴趣,但更感兴趣的是为什么这会导致问题。既然它可以键入整个元组(并因此键入其中的内容)似乎有些奇怪,那么为什么提取单个值会导致错误呢
final val (x,y) = {
    ("x" === "y") -> 0
}
implicit val (f,b) = (x,y)
final implicit val tuple = {
    ("x" === "y") -> 0
}