为什么Scala的类型推理器失败了这组涉及参数化类型的隐式参数?

时间:2012-07-02 21:07:31

标签: scala type-inference implicit type-erasure

我想定义一个使用类型T参数化的方法,该方法的行为取决于可以找到类型Box[T]的隐式参数。以下代码将此方法定义为foo。使用foo[Int]foo[String]进行调用时,无需按预期返回1"two"

事情变得奇怪的是方法栏。它定义为返回Int,而不是foo[Int]我只有foo。我希望编译器会推断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]类型的简单情况也编译得很好。该示例也位于下方,并使用arglebargle代替foobar

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有效?

2 个答案:

答案 0 :(得分:1)

其他人必须解释为什么类型推断机制无法处理这种情况,但如果您希望清理代码,则可能会这样做:

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]  
}

请注意:

  1. 我从bar中删除了类型注释,因此您只需指出一次类型(只是在您想要的不同位置)
  2. 我使用App而非弃用Application
  3. foo
  4. 的类型签名中使用上下文绑定

答案 1 :(得分:1)

这可能与SI-3346有关,虽然它是隐式转换的隐式参数,在这里你只有一个隐式转换。