eje*_*eje 7 scala implicit compiler-bug implicit-conversion implicits
这是一个简单的重现器,我在其中定义了一个带有隐式重新排序转换的"可交换"对类型.如果函数的参数f位于预先存在的命名值(t在示例中),则编译器会按预期应用隐式转换.但是,如果我尝试f直接调用literal CommutativePair,它会因类型错误而失败.在这种情况下,编译器不应用隐式重新排序转换.
object repro {
import scala.language.implicitConversions
case class CommutativePair[A, B](a: A, b: B)
object CommutativePair {
// Support a kind of commutative behavior via an implicit reordering
implicit def reorderPair[B, A](pair: CommutativePair[B, A]) =
CommutativePair(pair.b, pair.a)
}
// The idea is to allow a call to 'f' with Pair[Int, String] as well,
// via implicit reorder.
def f(p: CommutativePair[String, Int]) = p.toString
val t = CommutativePair(3, "c")
// This works: the implicit reordering is applied
val r1 = f(t)
// This fails to compile: the implicit reordering is ignored by the compiler
val r2 = f(CommutativePair(3, "c"))
}
Run Code Online (Sandbox Code Playgroud)
我相信它已经达到了 scala 推理的极限,这是由它搜索解决方案的顺序触发的。第一种情况:
val t = CommutativePair(3, "c")
Run Code Online (Sandbox Code Playgroud)
推理已将类型锁定为CommutativePair[Int,String],因为它是唯一可以根据参数工作的类型。所以当它调用时:
val r1 = f(t)
Run Code Online (Sandbox Code Playgroud)
Commutative[Int,String]它在=!=上得到类型不匹配Commutative[String,Int],然后它搜索隐式并找到上面的隐式。
在第二种情况下,scala 试图从外部找出类型:
val r2 = f(CommutativePair(3, "c"))
Run Code Online (Sandbox Code Playgroud)
f,必须采取Commutative[String,Int]。CommutativePair(...,...) 必须是Commutative[String,Int](因为它还没有从它的参数中找出它的类型)。CommutativePair(...)并发现它们的类型错误。但这不会触发隐式转换,因为它认为不匹配是在参数中,而不是在整体上CommutativePair(...)。事实上,锁定类型参数(通过显式传递它们或首先绑定到 val)可以修复错误。
| 归档时间: |
|
| 查看次数: |
341 次 |
| 最近记录: |