2015-06-17 37 views
11

İlk olarak, sorunumu doğru şekilde nasıl etiketleyeceğimi bilmiyorum. Bu, yararlı kaynaklar bulamadığım için de olabilir. Herhangi bir ipucu çok takdir edilmektedir. Tür sınıfı ve bağımlı türler

trait Context[T] 
{ 
    self => 

    trait Rule 
    { 
     def apply(value: T): Boolean 
    } 

    implicit class RichRule[A <: Rule](a: A) 
    { 
     def and[B <: Rule](b: B): and[A, B] = self.and(a, b) 
     def or[B <: Rule](b: B): or[A, B] = self.or(a, b) 
    } 

    sealed trait Group[A <: Rule, B <: Rule] extends Rule 
    { 
     def a: A 

     def b: B 

     override def apply(value: T) = ??? 
    } 

    case class and[A <: Rule, B <: Rule](a: A, b: B) extends Group[A, B] 
    case class or[A <: Rule, B <: Rule](a: A, b: B) extends Group[A, B] 
} 

yukarıdaki kodu göz önüne alındığında, şimdi tanımlamak ve zincir Rules s bu şekilde olabilir: Ben istendiği gibi bu işleri

new Context[String] 
{ 
    class MyRule extends Rule 
    { 
     override def apply(value: String) = true 
    } 

    case class A() extends MyRule 
    case class B() extends MyRule 

    val x1: A and B or A = A() and B() or A() 
} 

ama şimdi zor kısım geliyor. İki kurala nasıl katılacağınızı açıklayan Tip Sınıfı Combination'u tanıtmak istiyorum.

Bu Tür Sınıfı şimdi işleçlerle geçirilmelidir.

implicit class RichRule[A <: Rule](a: A) 
{ 
    def and[B <: Rule](b: B)(implicit c: AndCombination[A, B]): and[A, B] = ??? 
    def or[B <: Rule](b: B)(implicit c: OrCombination[A, B]): or[A, B] = self.or(a, b) 
} 

Hala bazı ince ayarlardan sonra çalışıyor.

implicit val c1 = new Combination[MyRule, MyRule] 
{ 
    type Result = MyRule 

    def combine(a: A, b: B): MyRule = a 
} 

val x: A and B = A() and B() 

Ancak daha karmaşık hale gelirse, işler parçalanıyor. Combination[and[A, B], A] eksik:

A() and B() and A() 

örtük bir eksik hata yükseltmek olacaktır. Ancak, bunun nasıl işleneceğini bilen (Combination[and[A, B]#Result, A]) and[A, B] (type Result = MyRule) örtük bileşiminin sonucunu kullanmak istiyorum.

val x: A and B or A kombine kurallarının tür bilgisini saklamak benim için önemli, son bir sonuç türüne birleştirmek kolay ama istediğim değil.

Bu, alabildiğim kadar yakın olsa da, derleme başarısız oluyor.

trait Context[T] 
{ 
    self => 

    trait Rule 

    trait Value extends Rule 

    trait Group[A <: Rule, B <: Rule] extends Rule 
    { 
     def a: A 

     def b: B 

     implicit val resolver: Resolver[_ <: Group[A, B]] 
    } 

    case class and[A <: Rule, B <: Rule](a: A, b: B)(implicit val resolver: Resolver[and[A, B]]) extends Group[A, B] 

    implicit class RichRule[A <: Rule](a: A) 
    { 
     def and[B <: Rule](b: B)(implicit resolver: Resolver[and[A, B]]) = self.and[A, B](a, b) 
    } 

    trait Resolver[-A <: Rule] 
    { 
     type R <: Value 

     def resolve(a: A): R 
    } 
} 

object O extends Context[String] 
{ 
    implicit val c1 = new Resolver[A and A] 
    { 
     override type R = A 

     override def resolve(a: O.and[A, A]) = ??? 
    } 

    implicit def c2[A <: Value, B <: Value, C <: Value](implicit r1: Resolver[A and B]) = new Resolver[A and B and C] 
    { 
     override type R = C 

     override def resolve(a: A and B and C): C = 
     { 
      val x: r1.R = r1.resolve(a.a) 
      new c2(x) 
      ??? 
     } 
    } 

    class c2[A <: Value, B <: Value](val a: A)(implicit r2: Resolver[A and B]) extends Resolver[A and B] 
    { 
     override type R = B 

     override def resolve(a: O.and[A, B]) = a.b 
    } 

    case class A() extends Value 

    val x: A and A and A = A() and A() and A() 
} 
+0

Hangi Scala sürümünü kullanıyorsunuz ve hangi IDE kullanıyorsunuz? – eliasah

+0

2.11.6 IntelliJ ile, sbt konsolu üzerinden derleme – Taig

cevap

9

kodunuzu derlemek edemez iken nedeni talimatıyla

new c2(x) 

derleyici x bir implicit r2: Resolver[A and B] ve tek tip bilgileri çözmek gerektiğini x türü olduğunu hangi r1.R.

Bu türden sorunlar, derleyici için daha fazla bilgi vermeyi ve bazı örtük parametreler eklemeyi gerektirir. Bir Resolver[A and B] gereksinim duyduğunuzda, başka bir Resolver[r1.R and C] çözmek için onun R türünü kullanamazsınız.

bu mevcut With
type ResolverAux[-A<:Rule,B] = Resolver[A] { type R = B } 

, Tür takma adını kullanarak ve ek jenerik parametreyi tanıtarak, o zaman kullanılan ilişkiyi r1.R1 = D ifade edebildiğini

implicit def c2[A <: Value, B <: Value, C <: Value,D<:Value](implicit r1: ResolverAux[A and B,D], r2:Resolver[D and C]):Resolver[A and B and C] = new Resolver[A and B and C] 
    { 
    override type R = C 

    override def resolve(a: A and B and C): C = 
    { 
     val x: r1.R = r1.resolve(a.a) 
     new c2[r1.R,C](x) 
     ??? 
    } 
    } 

Bildirimi sizin c2 imzasını yazabiliriz İkinci zımni r2'yi çözmek için r12

+0

Benim dağınık soru ve kodlarımı kazmak için çok teşekkür ederim. Buna gerçekten memnun olurum. Cevabınız çok umut verici görünüyor, ama başımı sarmak için biraz zaman alacak.Ben her zaman bu Aux şey bazı scalaz veya şekilsiz tökezledi zaman ne olduğunu merak ediyorum. – Taig

İlgili konular