2013-06-07 3 views
0

У меня есть следующий код:Scala: высший-kinded типов, прогнозы типа и ошибка несоответствия типа

trait M[Type[_]]{ 
    type T[X] = Type[X] 
    def from[A](f: T[A]): A 
} 
class ListM extends M[List]{ def from[A](f: T[A]) = f.head } 

class Trans[A, X[_], B <: M[X]](val r: X[Option[A]]) 
trait CurriedTrans[X[_], B <: M[X]]{ type Type[A] = Trans[A, X, B] } 
class TransM[X[_], B <: M[X]](val b: B) extends M[CurriedTrans[X, B]#Type]{ 
    def from[A] = (f: T[A]) => b.from(f.r).get 
} 

и я могу создать экземпляр переменного типа TRANSM два способов:

val x1 = new TransM[List, ListM](new ListM) 
val x2 = new TransM[ListM#T, ListM](new ListM) 

Я думаю, ListM # T является излишним параметр типа, так что я пытаюсь устранить ее:

trait M{ 
    type T[X] 
    def from[A](f: T[A]): A 
} 
class ListM extends M { 
    type T[X] = List[X] 
    def from[A](f: T[A]) = f.head 
} 

class Trans[A, B <: M](val r: B#T[Option[A]]) 
class TransM[B <: M](val b: B) extends M { 
    type T[X] = Trans[X, B] 
    def from[Y] = (f: T[Y]) => b.from(f.r).get 
} 

инстанцировать переменную

val x = new TransM[ListM](new ListM) 

К сожалению, вторая реализация не может быть скомпилирован из-за ошибки несоответствия типов:

type mismatch; 
found : f.r.type (with underlying type B#T[Option[Y]]) 
required: TransM.this.b.T[?] 
     def from[Y] = (f: T[Y]) => b.from(f.r).get 
             ^

Могу ли я решить эту проблему и упростить мой код или я должен написать шаблонный ListM # T везде?

+0

Первый блок кода не компилируется, метод 'from' в' TransM' определен с неправильной подписью. –

+0

Зачем вам нужен конкретный тип 'B <: M [X]' для 'TransM'? Разве 'M [X]' хватит? – ziggystar

ответ

0

@ziggystar говорит, что: Отбросьте связанный B и использовать M[X] непосредственно:

class TransM[X[_]](val b: M[X]) extends M[CurriedTrans[X, M[X]]#Type] { 
    def from[A](f: T[A]) = b.from(f.r).get 
} 

val x1 = new TransM(new ListM) 

Вы могли бы рассмотреть возможность сделать то же самое для Trans и CurriedTrans. Если вам нужен внутренний тип M, вы всегда можете выставить его через элемент типа Trans и CurriedTrans.

Смежные вопросы