2014-09-10 23 views
16

Kimin örneklerini bana bazı türünde bir değeri verecektir basit tip sınıf var varsayalım:örnekleri bir kovaryant tip sınıfın örneklerini oluşturma olmayan bir kovaryant bir

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

Ve bende bazı durumlarda:

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

Şimdi aynı şeyi yapar ancak türünü parametresinde covariant bir tip benzer (ama ilgisiz) sınıf var Bir almak için tek bir yol var çünkü

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

Şimdi, sadece iyi derlemek için implicitly[GiveMeA[Foo]] beklediğiniz: onun arkadaşı nesnede

bizim olmayan kovaryant tip sınıfının örnekleri gelen örneklerini oluşturmak için nasıl derleyici anlatmak GiveMeA[Foo] Burada sahip olduğumuz parçalar verilmiştir. Ama öyle değil (en azından 2.10.4 veya 2.11.2 ya üzerine):

bizim alakasız GiveMeJustA örneğinin kurtulmak ise
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]] 
         ^

, çalışır: Bu içindedir

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

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

GiveMeA[Foo] (veya GiveMeA[Foo]'un herhangi bir alt türünü) almak için bu örneğin GiveMeA.fromGiveMeJustA'u uygulamamızın hiçbir yolu olmamasına rağmen.

Bu benim için bir hataya benziyor, ancak bir şeyleri kaçırmam mümkün. Bu bir anlam ifade ediyor mu? Makul bir çözüm var mı?

cevap

2

Neden çalıştığını anlamıyorum, ancak aşağıdaki kod, geçerli durumda örtük başarılı bir şekilde çözer (en azından scala v-2.10.1'de).

Biz tür parametresi X tarafından yukarı doğru sınırlanan örtülü GiveMeJustA örneklerini aramak için örtülü GiveMeA[X] örneğini değiştirmek böylece GiveMeJustA[_ <: X]

arar: senin örneğin ilk etapta neden çalışmadığını Ancak, bu hala açıklıyor
object GiveMeA { 
    implicit def fromGiveMeJustA[X](implicit giveMe: GiveMeJustA[_ <: X]) : GiveMeA[X] = 
    new GiveMeA[X] { def apply() = giveMe() } 
} 
sonra beklenen çıkışı

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

yazdırabilirsiniz

Ancak en kısa zamanda yeni bir alt sınıfını tanıtmak olarak

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

ve örnek typeclass ilgili GiveMeJustA

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

derleyici (beklendiği gibi)

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

çözüm için çalışıyor şikayet verilen örnek. Ama benim durumumda, 'GiveMeJustA' kullanılmakta olan' Generic' kullanıyorum. Ve bu durumda çözüm işe yaramaz gibi görünüyor, sanırım makrolar yüzünden. – tksfz