2011-03-22 2 views
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) 
    } 
} 

내가 (2.8.1)에 REPL에서이 세션을 가지고

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 = [email protected] 

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
> trait UrlLike[T] { 

trait UrlLike[+T] { 
2

어떤 암시 적 모호성 관련하여, rule is (since Scala2.8) :

때 오버로드 된 방법 또는 암시 적, 각 방법의 두 가지 적용 가능한 대안을 비교하는 것 :

  • 갖는 더 구체적인 C를 인수,
  • 와 또 다른 점은 드 Fi를 적절한 서브에 네드되는 1 점을 얻는다.

두 가지 비교에서 더 많은 수의 점을 얻는다면 다른 대안이 "승리"할 수 있습니다.
대체로 동일한 인수 유형을 갖는 경우 하위 클래스에서 정의 된 인수가 우선합니다.

나는 URL 또는 URI 주위 implicits 그 기준을 다음과 같은 점 다른 세트를 얻을 수 있다고 생각하지 않습니다.

2

보고있는 오류 보고서에서 분명하지 않을 수도 있지만 UrlLike 객체에 정의 된 3 개의 모든 implicits가 모호성에 기여하고 있습니다 (예 : uri의 정의를 주석으로 처리하십시오. 모호성이 str과 ur 사이에 있다고보고 됨).

모호성의 이유는 UrlSupport.url의 형식 매개 변수 T가 사용할 수있는 암시 적 UrlLike 인스턴스가 있어야한다는 요구 사항에 의해서만 제한된다는 것입니다. 문자열, URL 및 URI는 모두 세 가지 암시 적 객체가 제공하는 UrlLike 인스턴스 덕분에 해당 요구 사항을 모두 만족시킵니다. 컴파일러는 당신을 위해 임의로 선택하지 않으므로 모호성을보고합니다.

물론 REPL 상호 작용의 마지막 두 단계에서했던 것처럼 형식 인수를 명시 적으로 지정하여 모호성을 해결하지 않는 한.

+0

형식 어미션 때문에 String/URL/URI 결과를 컴파일러에서 볼 수 없습니까? – IttayD

5

왜 작동하는지 예상 할 수 있지만 분명히 형식 유추 자의 반환 형식을 사용하여 T을 유추하지 않습니다. 나는 그것도 역시 기대할 것이다.

모호성의 경우 CanBuildFrom은 같은 "레벨"의 모든 것을 정의하지 않아서 모호하지 않습니다.예를 들어,이 모호성 문제 해결 :

scala> res0.url : URL 
<console>:16: error: type mismatch; 
found : String 
required: java.net.URL 
     res0.url : URL 
      ^

은 분명히 고려하지 않고 T 추론을하게 나타냅니다 그러나

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} 
} 

를, 그것은는 형식 유추가 원하는 방식으로 작동하지 것 고려해야 할 반환 유형입니다.