scala - 为什么 Scala 的类型推断器会因这组涉及参数化类型的隐式参数而失败?

标签 scala type-inference implicit type-erasure

我想定义一个使用 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] 类型的更简单情况也可以正常编译。该示例也在下面,并使用 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 行起作用?

最佳答案

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

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 的类型签名中使用上下文绑定(bind)

关于scala - 为什么 Scala 的类型推断器会因这组涉及参数化类型的隐式参数而失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11301191/

相关文章:

scala - 声明的隐含和顺序

scala - Akka Streams ActorRefSource 消息顺序

scala - 无法将 play.twirl.api.Html 对象与 play 2.3 连接起来

generics - Java 代码中 "? extends"上的 Scala 类型推断失败

scala - 为什么 Scala 类型与预期的 Int 不匹配?

c# - 转换 Dictionary<string,string> 时出现显式转换运算符错误

java - 同时运行同一功能的多个版本

scala - 在 Scala 中组合两个 Option[List[String]]

haskell - 如果函数的参数中未使用类型,如何指定函数的类型?

Hibernate 3.5 与 4 IDENTITY_INSERT 问题