質問
問題は、なぜ次のコードがタイプ推論で動作しないのか(以下は実証するREPLセッションです)、そしてそれを修正できますか?より具体的には、これはコンパイラーがリターンタイプを推測するために使用するCanBuildfromの使用とどのように違うのですか?
このコードを与えられた:
object S {
import java.net._
trait UrlLike[T] {
def url(s: String): T
}
object UrlLike {
implicit object str extends UrlLike[String]{def url(s: String) = s}
implicit object url extends UrlLike[URL]{def url(s: String) = new URL(s)}
implicit object uri extends UrlLike[URI]{def url(s: String) = new URI(s)}
}
trait UrlSupport {
val _url: String
def url[T : UrlLike]: T = implicitly[UrlLike[T]].url(_url)
}
}
私はこのセッションをREPL(2.8.1)に持っています:
scala> :load c:\temp\UrlTest.scala
Loading c:\temp\UrlTest.scala...
defined module S
scala> import java.net._
import java.net._
scala> import S._
import S._
scala> new UrlSupport{val _url = "http://example.com"}
res0: java.lang.Object with S.UrlSupport = $anon$1@155bd22
scala> res0.url : String
<console>:14: error: ambiguous implicit values:
both object uri in object UrlLike of type object S.UrlLike.uri
and object url in object UrlLike of type object S.UrlLike.url
match expected type S.UrlLike[T]
res0.url : String
^
scala> res0.url : URL
<console>:14: error: ambiguous implicit values:
both object uri in object UrlLike of type object S.UrlLike.uri
and object url in object UrlLike of type object S.UrlLike.url
match expected type S.UrlLike[T]
res0.url : URL
^
scala> res0.url[String]
res3: String = http://example.com
scala> res0.url[URL]
res4: java.net.URL = http://example.com
解決
> trait UrlLike[T] {
trait UrlLike[+T] {
他のヒント
なぜあなたがそれが機能することを期待するのかわかりますが、明らかに、タイプの推測者は返品タイプを使用して推測していません T
. 。私もそれを期待しています。
あいまいさについては、 CanBuildFrom
同じ「レベル」ですべてを定義しないだけで曖昧になることを避けます。たとえば、これは曖昧さの問題を解決します。
trait LowPriorityImplicits {
implicit object url extends UrlLike[URL]{def url(s: String) = new URL(s)}
implicit object uri extends UrlLike[URI]{def url(s: String) = new URI(s)}
}
object UrlLike extends LowPriorityImplicits {
implicit object str extends UrlLike[String]{def url(s: String) = s}
}
しかし、それはそうします いいえ タイプの推論をあなたが望むように動作させる:
scala> res0.url : URL
<console>:16: error: type mismatch;
found : String
required: java.net.URL
res0.url : URL
^
これは明らかにそれが作られることを示しています T
返品タイプを考慮せずに推論。
暗黙のあいまいさに関して、 ルールは(scala2.8以降):
過負荷の方法または暗黙的な方法の2つの異なる適用可能な代替案を比較する場合、各方法:
- 1つのポイントを取得します より具体的な議論があります,
- と別のポイント 適切なサブクラスで定義されています.
これら2つの比較でより多くのポイントを獲得した場合、別のポイントを獲得した場合、別の「勝ち」。
これは、特に、代替が同一の引数タイプを持っている場合、サブクラスで定義されたものが勝つことを意味します。
私は周りのインクリシッツを考えていません URL
また URI
これらの基準に従って、異なるポイントのセットを取得します。
エラーレポートからあなたが見ていることは明らかではないかもしれませんが、オブジェクトのurllikeで定義されている3つのインクリットはすべて曖昧さに貢献しています(たとえば、URIの定義をコメントしてみてください。 strとurlの間)。
あいまいさの理由は、urlsupport.urlの型パラメーターtは、それが利用可能な暗黙のurllikeインスタンスがあるという要件によってのみ制限されているためです。 String、URL、およびURIはすべて、3つの暗黙的なオブジェクトによって提供されたUrllikeインスタンスのおかげで、その要件も同様にその要件を満たしています。コンパイラはあなたのために任意にそれらのいずれかを選択するつもりはないので、あいまいさを報告します。
もちろん、REPL相互作用の最後の2つで行ったように、タイプ引数を明示的に指定することにより、曖昧さを解決しない限り。