【问题标题】:Scala type inference fails on overloaded methods despite non-conflicting signature尽管签名不冲突,但 Scala 类型推断在重载方法上失败
【发布时间】:2023-03-26 02:34:02
【问题描述】:
% scala                                                                     
Welcome to Scala 2.12.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.

scala>   trait Op[-Y, -Z, +A, +B] {
     |     def apply(other: (Y, Z)): (A, B)
     |   }
defined trait Op

scala>   implicit class RichTuple2[+A, +B](t: (A, B)) {
     |     def ~~~(other: Int): (A, B) = ???
     |     def ~~~[RA, RB](other: Op[A, B, RA, RB]): (RA, RB) = other.apply(t)
     |   }
defined class RichTuple2

scala>   def swap[A, B] = new Op[A, B, B, A] {
     |     override def apply(other: (A, B)) = (other._2, other._1)
     |   }
swap: [A, B]=> Op[A,B,B,A]

scala> (1, "foo") ~~~ swap
<console>:14: error: overloaded method value ~~~ with alternatives:
  [RA, RB](other: Op[Int,String,RA,RB])(RA, RB) <and>
  (other: Int)(Int, String)
 cannot be applied to (Op[Nothing,Nothing,Nothing,Nothing])
       (1, "foo") ~~~ swap

如果我删除第一个 ~~~(other: Int) 方法,那么它就可以工作:

scala>   trait Op[-Y, -Z, +A, +B] {
     |     def apply(other: (Y, Z)): (A, B)
     |   }
defined trait Op

scala>   implicit class RichTuple2[+A, +B](t: (A, B)) {
     |     def ~~~[RA, RB](other: Op[A, B, RA, RB]): (RA, RB) = other.apply(t)
     |   }
defined class RichTuple2

scala>   def swap[A, B] = new Op[A, B, B, A] {
     |     override def apply(other: (A, B)) = (other._2, other._1)
     |   }
swap: [A, B]=> Op[A,B,B,A]

scala> (1, "foo") ~~~ swap
res0: (String, Int) = (foo,1)

问题是为什么在这种情况下类型推断和方法选择会失败?方法~~~(other: Int) 接受一个与swap 的类型完全不相关的参数(其中是Op 类型)。有人知道解决方法吗?

【问题讨论】:

    标签: scala types type-inference


    【解决方案1】:

    当将隐式与重载混合使用时,scalac 有时难以找到正确的隐式或推断正确的类型。

    关于这个主题有几张 jira 票,而这个特定的一张:SI-9523,似乎与您的问题中的问题相同。

    在您的情况下,当~~~ 重载时,scalac 无法推断swap 的类型参数,因此使用swap[Int, String] 对其进行注释应该可以工作。

    Scala 中通常不鼓励重载(参见Why "avoid method overloading"?)和(http://www.wartremover.org/doc/warts.html),因此最好的解决方案是避免重载。

    【讨论】:

    • 好的。所以这是一个(另一个)Scala bug :)
    • 实际上,这通常是重载的限制,而不是与隐式相关的错误。通过让编译器选择适当的重载 一次性推断出 swap 方法的类型参数,您对编译器的要求有点过高。在关于重载解析和本地类型推断的段落中是specced
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 2017-06-22
    相关资源
    最近更新 更多