scala - 为什么提取和分配单个元组值会导致递归隐式搜索?
问题描述
这是产生此错误的代码:
构建.sbt
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"ai.x" %% "safe" % "0.1.0"
)
scalacOptions := Seq("-Ytyper-debug") // Only add this if you want to see a bunch of stuff
测试.scala
import ai.x.safe._
package object foo {
final implicit val (enc, dec) = {
("x" === "y") -> 0
}
}
试图编译它会导致这个错误:
[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
我当然可以通过执行以下操作使其编译:
final val (x,y) = {
("x" === "y") -> 0
}
implicit val (f,b) = (x,y)
由于在定义主体时不存在隐式,因此在定位from可以应用并使代码正常工作{}
时,它们不会干扰编译器的隐式搜索。现在我对此并没有真正的问题,因为它确实有意义,因为人们可以定义惰性递归序列化器和其他可以毫无问题地使用自身的隐式事物。因此,编译器当然应该查看被定义为可能的应用程序以使某些东西工作的隐式。===
SafeEquals
String
但对我来说奇怪的是,如果您在分配期间不直接提取元组,这会起作用:
final implicit val tuple = {
("x" === "y") -> 0
}
显然这不是我想要做的,因为我希望元组中的两件事都是隐式的(在我的真实情况下,它是来自 circe 的编码器/解码器对)。但是对我来说很奇怪的是,使用(我相信是)Tuple2 的提取器会导致这个编译器错误,并搜索隐式。谁能告诉我为什么会发生这种情况或导致这种行为的原因是什么?我很想知道更多关于我在调试输出中看到的内容。为什么解析元组内部每个事物的类型会导致编译器错误,但解析整个元组的类型不会导致任何问题?
解决方案
推荐阅读
- php - AWS ec2 中的 Cron 作业,但无法正常工作
- create-react-app - 如何从 Firebase 托管中取消部署 React Web 应用程序
- mvvm - 具有复杂 MVVM 的 SwiftUI(存储库 + 嵌套 ObservedObject)
- java - 为什么在android webview中授予相机权限后再次打开应用程序时相机会工作?
- azure - 向 ARM 模板参数文件添加新参数
- jsonschema - 如何在 json 模式中指示动态添加支持?
- javascript - 如何在键入时使“数字”输入不可编辑?
- python - 使用 node js 进行非对称加密和使用 Python 进行解密
- reactjs - 使用 dangerouslySetInnerHTML 解析 HTML 时如何忽略 img 标签?
- sql-server - 来自 SQL Server 的 Moodle 身份验证