我想定义一个使用 T
类型参数化的方法,该方法的行为取决于可以找到 Box[T]
类型的隐式参数。以下代码将此方法定义为 foo
。当使用 foo[Int]
或 foo[String]
调用时,它将毫无问题地返回 1
或 "two"
正如预期的那样。
事情变得奇怪的是方法栏。它被定义为返回一个 Int
,但我只有 foo
而不是 foo[Int]
。我希望编译器能够推断出 T
必须是 Int
类型。它没有这样做,而是失败了:
bash $ scalac Code.scala
Types.scala:15: error: ambiguous implicit values:
both value one in object Main of type => Main.Box[Int]
and value two in object Main of type => Main.Box[java.lang.String]
match expected type Main.Box[T]
def bar: Int = foo
^
one error found
是什么导致了这个错误?将 foo
替换为 foo[Int]
可以正常编译。没有 Box[T]
类型的更简单情况也可以正常编译。该示例也在下面,并使用 argle
和 bargle
而不是 foo
和 bar
。
object Main extends Application {
case class Box[T](value: T)
implicit val one = Box(1)
implicit val two = Box("two")
def foo[T](implicit x: Box[T]): T = {
x.value
}
// does not compile:
// def bar: Int = foo
// does compile
def bar: Int = foo[Int]
println(bar)
// prints 1
// the simpler situation where there is no Box type
implicit val three = 3
implicit val four = "four"
def argle[T](implicit x: T): T = x
def bargle: String = argle
println(bargle)
// prints "four"
}
这段代码中发生了什么导致了这种行为?隐式参数、类型推断和删除的相互作用会导致问题吗?有没有办法修改此代码,使 def foo: Int = bar
行起作用?
最佳答案
其他人必须解释为什么类型推断机制无法处理这种情况,但如果您想要清理代码,您可能可以这样做:
object Test extends App {
case class Box[T](value: T)
implicit val one: Box[Int] = Box(1)
implicit val two: Box[String] = Box("two")
def foo[T : Box]: T = implicitly[Box[T]].value
val bar = foo[Int]
}
请注意:
- 我从
bar
中删除了类型注释,因此您实际上只需指示一次类型(只是在与您想要的不同的位置) - 我正在使用
App
而不是已弃用的Application
- 在
foo
的类型签名中使用上下文绑定(bind)
关于scala - 为什么 Scala 的类型推断器会因这组涉及参数化类型的隐式参数而失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11301191/