8

問題は、次のコードが型推論で機能しないのはなぜですか (以下は、デモ用の 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 
4

4 に答える 4

5

なぜ機能すると期待するのかはわかりますが、明らかに、型推論器は戻り値の型を使用して推論していません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これは、戻り値の型を考慮せずに明らかに推論を行うことを示しています。

于 2011-03-22T14:43:35.920 に答える
4
> trait UrlLike[T] {

trait UrlLike[+T] {
于 2011-03-22T15:51:22.563 に答える
2

暗黙のあいまいさに関しては、ルールは次のとおりです (Scala2.8以降) :

オーバーロードされたメソッドまたは暗黙の 2 つの適用可能な代替案を比較すると、各メソッドは次のようになります。

  • より具体的な引数を持つことで1 ポイントを獲得し、
  • 適切なサブクラスで定義されるためのもう 1 つのポイントです。

これらの 2 つの比較でより多くのポイントを獲得した場合、代替案は別の選択肢に「勝ちます」。
これは特に、代替の引数の型が同じ場合、サブクラスで定義されたものが優先されることを意味します。

私は暗黙のうちにそれらの基準に従って別のポイントのセットを取得しURLたり取得したりしないと思います。URI

于 2011-03-22T14:14:02.723 に答える
2

表示されているエラー レポートからは明らかではないかもしれませんが、オブジェクト UrlLike で定義されている 3 つの暗黙の要素すべてがあいまいさの原因になっています (たとえば、uri の定義をコメント アウトしてみると、あいまいさが次のように報告されていることがわかります)。 str と url の間)。

あいまいさの理由は、UrlSupport.url の型パラメーター T が、使用可能な暗黙の UrlLike インスタンスが存在するという要件によってのみ制限されるためです。文字列、URL、および URI はすべて、3 つの暗黙的なオブジェクトによって提供される UrlLike インスタンスのおかげで、その要件を等しく満たしています。コンパイラはそれらのいずれかを恣意的に選択するわけではないため、あいまいさを報告します。

もちろん、最後の 2 つの REPL 対話で行ったように、型引数を明示的に指定してあいまいさを解決しない限り。

于 2011-03-22T14:20:45.203 に答える