2015-06-17 1 views
11

Прежде всего, я не знаю, как правильно пометить мою проблему. Это также может быть причиной того, что я не нашел полезных ресурсов. Любые советы заслуживают высокой оценки.Тип типа и зависимые типы

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

Учитывая приведенный выше код, теперь я могу определить и цепь Rules S таким образом:

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

Это работает, как я предполагал, но теперь наступает сложная часть. Я хочу ввести Type Class Combination, в котором объясняется, как присоединиться к двум правилам.

trait Combination[-A <: Rule, -B <: Rule] 
{ 
    type Result <: Rule 

    def combine(a: A, b: B): Result 
} 
trait AndCombination[-A <: Rule, -B <: Rule] extends Combination[A, B] 
trait OrCombination[-A <: Rule, -B <: Rule] extends Combination[A, B] 

Этот класс класса теперь должен передаваться с операторами.

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

Это еще работает после некоторых настроек.

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

Но если это усложняется, все разваливается.

A() and B() and A() 

Поднимем неявную ошибку недостающий: Combination[and[A, B], A] отсутствует. Но я хочу, чтобы он использовал результат неявной комбинации and[A, B] (type Result = MyRule), который он уже знает, как обращаться (Combination[and[A, B]#Result, A]).

Для меня важно хранить информацию о комбинированных правилах val x: A and B or A, сворачивая их вместе с конечным типом результата, но это не то, что я хочу.

Это как можно ближе, но это не скомпилировано.

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

Какую версию Scala вы используете и какую IDE? – eliasah

+0

2.11.6 с IntelliJ, скомпилирование через консоль sbt, хотя – Taig

ответ

9

Причина, пока ваш код не может скомпилировать в том, что в инструкции

new c2(x) 

Компилятор необходимо разрешить implicit r2: Resolver[A and B] от x и только информацию о типе доступного является тип x, который есть r1.R.

Этот тип проблем требует создания дополнительной информации о типе, доступной компилятору, и добавления неявного параметра. Когда вам понадобится Resolver[A and B], вы не можете использовать его тип R для разрешения другого Resolver[r1.R and C].

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

При этом в наличии, вы можете переписать подпись вашего c2

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

Обратите внимание, что с помощью псевдонима типа и введения дополнительного общего параметра, я могу выразить свое отношение r1.R1 = D, который затем используются для решения второго неявного r2

+0

Большое спасибо за то, что я прорыл свой грязный вопрос и код. Я действительно ценю это. Ваш ответ выглядит очень многообещающим, но, вероятно, мне понадобится время, чтобы обнять вокруг него голову.Мне всегда было интересно, что это за Aux, когда я наткнулся на какой-то скалаз или бесформенный. – Taig