【发布时间】:2017-04-04 05:33:56
【问题描述】:
我可以使用建议来调试隐式:
我想使用隐式,x:
type T
trait HasT {
implicit def x: T = ...
}
但我还需要从某个包foo 导入通配符。我尝试了两种不同的方式来介绍两者:
class UseT extends HasT {
import foo._
implicitly[T] // fails! "could not find implicit value"
// use foo stuff
}
和
class UseT {
object hasT extends HasT
import hasT.x
import foo._
implicitly[T] // fails! "could not find implicit value"
}
两者都以“找不到”(不是“模糊的隐含值”)失败。
当隐式标识符 x: T 可在方法调用点通过继承或导入访问时,就会发生这种情况。
我的解决方法是在导入之前将 x 重新绑定到隐式 val。以下两项工作:
implicit val x2: T = implicitly[T]
import foo._
implicitly[T] // works!
和
implicit val x2: T = x
import foo._
implicitly[T] // works!
foo 中的什么值可能会导致这种行为?
我的第一个猜测是foo 中存在一些竞争隐式,但如果它具有更高的优先级,那么下面的implicitly 仍然可以工作,如果它是一个模棱两可的隐式,我会得到一个不同的不同的错误。
编辑:Miles Sabin 的猜测是正确的!我发现隐含的阴影:timeColumnType。我仍然不完全理解这是如何工作的,因为 Som Snytt 观察到阴影隐式是通配符导入的(较低优先级),而阴影是继承的(最高优先级的一部分),所以我将把整个帖子留给后代。
撤回:由miles sabin 提供的第二个猜测是implicit shadowing。我已经澄清了我的帖子以排除这种可能性。如果我尝试过package hasT extends HasT; import hasT._,这种情况与我的错误一致,但正如 som-snytt 指出的那样,这两种情况不会导致阴影。
在我的具体情况下,这可以通过更改我尝试使用的隐式名称来确认。
(这是错误的。在使用此测试进行验证时,我可能错过了publishLocal 或reload。)
context:我实际上是在尝试使用 slick。上面隐含的T其实是一个列类型映射:
import slick.driver.JdbcProfile
class Custom { ... } // stored as `Long` in postgres
trait ColumnTypes {
val profile: JdbcProfile
import profile.api._ // this is `foo` above
type T = profile.BaseColumnType[Custom]
implicit def customColumnType: T =
MappedColumnType.base[Custom, Long](_.toLong, Custom.fromLong)
}
class DatabaseSchema(val profile: JdbcProfile) extends ColumnTypes {
// `implicitly[T]` does not fail here.
import profile.api._ // this is also `foo` above
// `implicitly[T]` fails here, but it's needed for the following:
class CustomTable(tag: Tag) extends Table[Custom](tag, "CUSTOMS") {
// following fails unless I rebind customColumnType to a local implicit
def custom = column[Custom]("CUSTOM")
def * = custom
}
}
api/foo 的类型是JdbcProfile.API。冒犯的隐含可能是here,但我不知道为什么。我会尝试阻止其中一些被导入,看看是否可以缩小范围。
【问题讨论】:
-
您的简化示例编译。它应该吗?我注意到您没有将
T别名为profile.api.BaseColu...。可能这也不重要。 -
@som-snytt 对!如果implicit 被命名为
timeColumnType,它将不会编译。迈尔斯怀疑隐含阴影是正确的。 -
我已经开始使用名称中的完整包路径来命名我的隐式,以避免将来发生这种情况。
-
好的,谢谢。你的代码没有错……
标签: scala scope slick implicits shadowing