2017-10-09 9 views
0
% 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 

にもかかわらず、オーバーロードされたメソッドを上の失敗、それは動作します:Scalaの型推論は、非矛盾署名

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のタイプにはまったく関連しないパラメータをとります(with Opタイプ)。誰もが回避策を認識していますか?

答えて

1

scalacは、適切なimplicitsを見つけたり、過負荷のimplicitsを混ぜるときに正しいタイプを推測することができないことがあります。

このトピックに関するいくつかのジラ・チケットがあります。この特定のチケットは、SI-9523です。ご質問の問題と同じ問題があるようです。

~~~がオーバーロードされている場合、scalacはswapの型引数を推論することができませんので、swap[Int, String]で注釈を付けると効果があります。

オーバーロードは、Scala(Why "avoid method overloading"?を参照)と(http://www.wartremover.org/doc/warts.html)では一般的に推奨されていません。オーバーロードを避けることをお勧めします。

+0

したがって、それは(nother)Scalaのバグです:) –

+0

実際には、これは一般的なオーバーロードの制限であり、implicitsに関連するバグではありません。適切なオーバーロードを選択し、あなたの 'swap'メソッドの型引数を推測することによってコンパイラを少し過ごしています。解像度のオーバーロードとローカルタイプの推論に関する段落の[specced](https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#overloading-resolution)です。 –