2014-09-10 5 views
16

내가 누구의 인스턴스 나에게 몇 가지 유형의 값을 제공하는 간단한 형식의 클래스있어 가정합니다의 인스턴스에서 공변 형 클래스의 인스턴스를 생성 비 공변 한

trait GiveMeJustA[X] { def apply(): X } 

을 그리고있어 어떤 경우 :

trait GiveMeA[+X] { def apply(): X } 
:

case class Foo(s: String) 
case class Bar(i: Int) 

implicit object GiveMeJustAFoo extends GiveMeJustA[Foo] { 
    def apply() = Foo("foo") 
} 

implicit object GiveMeJustABar extends GiveMeJustA[Bar] { 
    def apply() = Bar(13) 
} 

는 지금은 같은 일을하지만 형식 매개 변수의 공변 된 입력 비슷한 (하지만 관련이없는) 클래스가 를 얻을 수있는 하나 개의 방법이 있기 때문에

object GiveMeA { 
    implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[X]): GiveMeA[X] = 
    new GiveMeA[X] { def apply() = giveMe() } 
} 

지금 내가 잘 컴파일 implicitly[GiveMeA[Foo]]을 기대 : 컴패니언 객체에서

우리는 우리의 비 공변 형 클래스의 인스턴스에서 인스턴스를 생성하는 방법을 컴파일러에게 GiveMeA[Foo] 우리는 여기에 조각을주었습니다. 그러나 그렇지 않은 (적어도 2.10.4 또는 2.11.2 중 하나에) :

우리는 우리의 무관 GiveMeJustA 예를 제거하면
scala> implicitly[GiveMeA[Foo]] 
<console>:16: this.GiveMeA.fromGiveMeJustA is not a valid implicit value for GiveMeA[Foo] because: 
hasMatchingSymbol reported error: ambiguous implicit values: 
both object GiveMeJustAFoo of type GiveMeJustAFoo.type 
and object GiveMeJustABar of type GiveMeJustABar.type 
match expected type GiveMeJustA[X] 
       implicitly[GiveMeA[Foo]] 
         ^
<console>:16: error: could not find implicit value for parameter e: GiveMeA[Foo] 
       implicitly[GiveMeA[Foo]] 
         ^

, 그것을 작동합니다 : 이것은에

scala> implicit def GiveMeJustABar: List[Long] = ??? 
GiveMeJustABar: List[Long] 

scala> implicitly[GiveMeA[Foo]] 
res1: GiveMeA[Foo] = [email protected] 

을 이 인스턴스에 GiveMeA.fromGiveMeJustA을 적용하여 GiveMeA[Foo] (또는 모든 하위 유형 GiveMeA[Foo])을 얻는 방법은 없다는 사실에도 불구하고.

이것은 나에게 버그처럼 보입니다.하지만 뭔가 누락 된 것 같습니다. 이게 말이 되니? 적절한 해결 방법이 있습니까?

답변

2

왜 작동하는지 모르겠지만 다음 코드는 현재의 경우 (적어도 scala v-2.10.1 이상에서는) 암시 적으로 성공적으로 해결됩니다.

우리는 형식 매개 변수가 X에 의해 위쪽으로 묶여있다 암시 GiveMeJustA 인스턴스를 검색하는 암시 적 GiveMeA[X] 인스턴스를 변경, 따라서 그것은 GiveMeJustA[_ <: X]

검색 : 귀하의 예를 들어 첫 번째 장소에서 작동하지 않는 이유 그러나, 이것은 아직도 설명
object GiveMeA { 
    implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[_ <: X]) : GiveMeA[X] = 
    new GiveMeA[X] { def apply() = giveMe() } 
} 
우리는 다음 예상되는 출력

val a = implicitly[GiveMeA[Foo]] 
println(a()) // prints "Foo(foo)" 

,369 인쇄 할 수 있습니다

그러나, 곧 우리는 새로운 서브 클래스를 소개로

case class FooChild(s: String) extends Foo(s) 

및 인스턴스 typeclass 각각의 GiveMeJustA

implicit object GiveMeJustAFooChild extends GiveMeJustA[FooChild] { 
    def apply() = FooChild("fooChild") 
} 

컴파일러 (예상대로)

error: could not find implicit value for parameter e: GiveMeA[Foo] 
    val a = implicitly[GiveMeA[Foo]] 
+0

이 솔루션은 작동 불평 주어진 예. 하지만 제 경우에는'GiveMeJustA'가 사용되는 곳에서'Generic'을 사용하고 있습니다. 그리고 그 경우 솔루션이 작동하지 않는 것처럼 보입니다. 매크로 때문에 추측하고 있습니다. – tksfz

관련 문제