我可以使用调试隐式的建议:
我想使用隐式的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
仍然有用,如果它是含糊不清的隐含的,我可以使用package hasT extends HasT; import hasT._
。 d得到一个不同的错误。
编辑:Miles Sabin的猜测是正确的!我发现阴影是隐含的:timeColumnType。我仍然不完全理解这是如何工作的,因为Som Snytt观察到隐藏的阴影是通配符导入(优先级较低),而阴影是继承的(优先级最高的部分),所以我会离开这里的全部帖子都是后人。
收回:由sabin提供的第二次猜测是implicit shadowing。我澄清了我的帖子以排除这种可能性。如果我尝试 publishLocal
,那么这种情况会与我的错误一致,但正如som-snytt指出的那样,这两种情况不会导致阴影。
在我的具体情况下,可以通过更改隐含的I尝试使用的名称来确认。
(这是错误的。在使用此测试进行验证时,我可能错过了reload
或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
/ Some NuGet packages are missing from the solution.
The packages need to be restored in order to build the dependency graph.
Restore the packages before performing any operations
的类型为JdbcProfile.API
。违规的隐含可能是here,但我不知道为什么。我会尝试阻止其中一些进口,看看我是否可以缩小它。
答案 0 :(得分:8)
我认为foo
最有可能包含名为x
的定义。从({1}}导入(通配符)时,它会影响本地定义,
foo
答案 1 :(得分:2)
这显然是隐式搜索中的一个错误。
首先,符合条件的是可以访问的所有标识符x 没有前缀的方法调用的点,表示隐式 定义或隐含参数。因此,合格的标识符可以 是本地名称,或封闭模板的成员,或者它可能是 通过import子句可以在没有前缀的情况下访问它。
在示例中,未加前缀的x
表示继承的符号。如果没有前缀,则无法访问X.x
。
隐式搜索正在破坏导入。
$ scala
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { def x: Int = 42 }
trait T { def x: Int = 17 }
object Y extends T {
import X._
def f = x
}
// Exiting paste mode, now interpreting.
defined object X
defined trait T
defined object Y
scala> Y.f
res0: Int = 17
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { implicit def x: Int = 42 }
trait T { implicit def x: Int = 17 }
object Y extends T {
import X._
def f: Int = implicitly[Int]
}
// Exiting paste mode, now interpreting.
<pastie>:19: error: could not find implicit value for parameter e: Int
def f: Int = implicitly[Int]
^
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { implicit def x: Int = 42 }
trait T { implicit def x: Int = 17 }
object Y extends T {
import X.{x => _, _} // avoids bug, but is redundant
def f: Int = implicitly[Int]
}
// Exiting paste mode, now interpreting.
defined object X
defined trait T
defined object Y
scala>
使用REPL的另一个示例是这样的:
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { def x: Int = 42 }
object Y { implicit def x: Int = 17 }
object Z {
import Y.x
def f = {
import X._
x
}
}
// Exiting paste mode, now interpreting.
<pastie>:19: error: reference to x is ambiguous;
it is imported twice in the same scope by
import X._
and import Y.x
x
^
x
根本不可用,并且隐式被正确排除。
只是为了确认:
$ scala -Xlog-implicits
Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> :pa
// Entering paste mode (ctrl-D to finish)
object X { implicit def x: Int = 42 }
trait T { implicit def x: Int = 17 }
object Y extends T {
import X._
def f: Int = implicitly[Int]
}
// Exiting paste mode, now interpreting.
<console>:17: x is not a valid implicit value for Int because:
candidate implicit method x in object X is shadowed by method x in trait T
def f: Int = implicitly[Int]
^
<console>:17: x is not a valid implicit value for Int because:
candidate implicit method x in object X is shadowed by method x in trait T
def f: Int = implicitly[Int]
^
<console>:17: error: could not find implicit value for parameter e: Int
def f: Int = implicitly[Int]
^
scala>