这是一个简单的复制器,我在其中定义了一个"交换"带有隐式重新排序转换的对类型。如果函数f
的参数位于预先存在的命名值(示例中为t
),则编译器会按预期应用隐式转换。但是,如果我尝试直接在文字f
上调用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"))
}
答案 0 :(得分:2)
我认为它正在达到scala推理的极限,由搜索解决方案的顺序触发。在第一种情况:
val t = CommutativePair(3, "c")
推理已将类型锁定为CommutativePair[Int,String]
,因为它是唯一可以根据参数工作的类型。所以当它打电话时:
val r1 = f(t)
Commutative[Int,String]
=!= Commutative[String,Int]
上的类型不匹配,然后搜索implicits并找到上面的那个。
在第二种情况下,scala正试图找出类型,从外部开始工作:
val r2 = f(CommutativePair(3, "c"))
f
,必须采用Commutative[String,Int]
。CommutativePair(...,...)
必须为Commutative[String,Int]
(因为,它还没有从中找出它的类型' s参数,但)。CommutativePair(...)
的参数并发现它们是错误的类型。但这不会触发隐式转换,因为它认为不匹配在参数中,而不是整个CommutativePair(...)
。实际上,锁定类型params(通过显式传递它们或通过首先绑定到val)来修复错误。