2014-09-14 31 views
48

varsayalım Ben Biçimsizler eşçarpımı tüm türleri tekil türleri olduğunu kanıtlayan bir tür sınıf var:o tekil tipleri tip sınıfı örneğini oluştururken tekil türleridir ispat edemezsin

import shapeless._ 

trait AllSingletons[A, C <: Coproduct] { 
    def values: List[A] 
} 

object AllSingletons { 
    implicit def cnilSingletons[A]: AllSingletons[A, CNil] = 
    new AllSingletons[A, CNil] { 
     def values = Nil 
    } 

    implicit def coproductSingletons[A, H <: A, T <: Coproduct](implicit 
    tsc: AllSingletons[A, T], 
    witness: Witness.Aux[H] 
): AllSingletons[A, H :+: T] = 
    new AllSingletons[A, H :+: T] { 
     def values = witness.value :: tsc.values 
    } 
} 

Biz gösterebiliriz sonra

sealed trait Foo 
case object Bar extends Foo 
case object Baz extends Foo 

Ve:

scala> implicitly[AllSingletons[Foo, Bar.type :+: Baz.type :+: CNil]].values 
res0: List[Foo] = List(Bar, Baz) 

Şimdi tarak istiyoruz basit bir ADT birlikte çalıştığını bize ADT bir heap temsilini vereceğiz ki şekilsiz en Generic mekanizma ile bu ine:

trait EnumerableAdt[A] { 
    def values: Set[A] 
} 

object EnumerableAdt { 
    implicit def fromAllSingletons[A, C <: Coproduct](implicit 
    gen: Generic.Aux[A, C], 
    singletons: AllSingletons[A, C] 
): EnumerableAdt[A] = 
    new EnumerableAdt[A] { 
     def values = singletons.values.toSet 
    } 
} 

Ben implicitly[EnumerableAdt[Foo]] çalışmak bekleyebilirsiniz fakat öyle değil. Biz niye hakkında bazı bilgiler almak için -Xlog-implicits kullanabilirsiniz:

<console>:17: shapeless.this.Witness.apply is not a valid implicit value for 
    shapeless.Witness.Aux[Baz.type] because: 
Type argument Baz.type is not a singleton type 
       implicitly[EnumerableAdt[Foo]] 
         ^
<console>:17: this.AllSingletons.coproductSingletons is not a valid implicit 
    value for AllSingletons[Foo,shapeless.:+:[Baz.type,shapeless.CNil]] because: 
hasMatchingSymbol reported error: could not find implicit value for parameter 
    witness: shapeless.Witness.Aux[Baz.type] 
       implicitly[EnumerableAdt[Foo]] 
         ^
<console>:17: this.AllSingletons.coproductSingletons is not a valid implicit 
    value for AllSingletons[Foo,this.Repr] because: 
hasMatchingSymbol reported error: could not find implicit value for parameter 
    tsc: AllSingletons[Foo,shapeless.:+:[Baz.type,shapeless.CNil]] 
       implicitly[EnumerableAdt[Foo]] 
         ^
<console>:17: this.EnumerableAdt.fromAllSingletons is not a valid implicit 
    value for EnumerableAdt[Foo] because: 
hasMatchingSymbol reported error: could not find implicit value for parameter 
    singletons: AllSingletons[Foo,C] 
       implicitly[EnumerableAdt[Foo]] 
         ^
<console>:17: error: could not find implicit value for parameter e: 
    EnumerableAdt[Foo] 
       implicitly[EnumerableAdt[Foo]] 
         ^

Baz.type

açıkçası olsa bir tekil tipi olduğunu.

implicit val barSingleton = Witness[Bar.type] 
implicit val bazSingleton = Witness[Baz.type] 

Ve her nasılsa şimdi çalışıyor: Biz sadece eğlence için elle kapsamında Witness örneklerini koyarak deneyebilirsiniz bu örnekleri olanları ise bu kapsamda çalışacak neden anlamıyorum

scala> implicitly[EnumerableAdt[Foo]].values 
res1: Set[Foo] = Set(Bar, Baz) 

Witness.apply makro yöntemiyle oluşturulmuştur (bunları oluşturmak için kullandığımız). Burada neler oluyor? Kurucuları manuel olarak numaralandırmamızı gerektirmeyen uygun bir çözüm var mı?

+1

Son zamanlarda bu alanda birkaç hata giderdim ... en son anlık görüntüyle tekrar deneyin. –

+0

Hmm, şans yok - aynı sonuç. –

+2

Bugün daha fazla tweaks itti ... üçüncü kez şanslı? –

cevap

22

Bu, en yeni shapeless 2.1.0-SNAPSHOT'unki gibi yazılmıştır.