【发布时间】:2016-06-10 09:48:08
【问题描述】:
我收到一个奇怪的编译器错误,该错误实际上存在但由于某种原因无法找到。所以我构建了一个重现神秘行为的小测试用例。
trait Hide {
type T
}
object HideString extends Hide {
override type T = String
}
object HideBool extends Hide {
override type T = Boolean
}
简单类型用作隐式转换的明确目标。
def id[H <: Hide, C](x : C)(implicit ev : C => H#T) : H#T = ev(x)
def drop[H <: Hide, C](x : C)(implicit ev : C => H#T) : Int = {
println(ev(x))
1
}
def idSeq[H <: Hide, C](x : Seq[C])(implicit ev : Seq[C] => Seq[H#T]) : Seq[H#T] = ev(x)
def dropSeq[H <: Hide, C](x : Seq[C])(implicit ev : Seq[C] => Seq[H#T]) : Int = {
println(ev(x))
1
}
依赖隐式转换的方法。它基本上是 2x2 矩阵。 id 方法返回转换后的类型,drop 方法在内部使用转换并返回一些常量。普通方法对精确隐式转换的类型进行操作,Seq 方法对序列进行操作。
implicit def exString(x : String) : HideString.type#T = x
implicit def highString[F[_]](x : F[String]) : F[HideString.type#T] = x
以上隐式转换highString 是用高阶类型定义的。
val s1 = id("sdf")
val s2 = drop("aero")
val r1 = idSeq(Seq("a", "bc"))
val r2 = dropSeq(Seq("i", "IO"))
尝试实际使用转换会给我带来一个错误:
ImplicitResolution.scala:98: error: No implicit view available from Seq[String] => Seq[test.implicits.HighReduction.Hide#T].
val r2 = dropSeq(Seq("i", "IO"))
这可以概括为以下矩阵:
| | id | drop |
|--------+------+------|
| normal | pass | pass |
| seq | pass | fail |
如果我对dropSeq 方法使用精确定义的隐式转换,则可以正常找到:
implicit def seqBool(x : Seq[Boolean]) : Seq[HideBool.type#T] = x
val a1 = idSeq(Seq(true, false))
val a2 = dropSeq(Seq(false, true))
此外,如果我明确指定隐式参数 dropSeq 开始工作:
val r2i = dropSeq(Seq("i", "IO"))(highString[Seq] _)
这是最奇怪的事情。 highString 隐式符合所有要求。并且它被声明为implicit,所以它应该被编译器找到。在idSeq 的情况下,它实际上是被发现的。那么,为什么在dropSeq 的情况下会忽略它呢?
【问题讨论】: