2011-04-03 25 views
12

estoy tratando desesperadamente de resolver el siguiente:aplicación parcial de los parámetros de tipo

trait Access[Res[_]] { def access[C]: Res[C] } 

trait CList[C1, A] extends Access[CList[_, A]] // ?! 

def test[C1, C2, A](c: CList[C1, A]): CList[C2, A] = c.access[C2] 

scalac sólo dice: "error: illegal cyclic reference involving trait CList". ¿Cómo puedo hacer esta compilación?

Respuesta

13

que podría estar interesado en el tipo de lambdas La aplicación parcial que utilizó en su respuesta es en realidad implemented in scalaz Sin embargo, como el código tiende a ser menos legible, empezaron a usar el tipo lambdas. El tipo en cuestión podría escribirse como

({type λ[α] = CList[α,A]})#λ 

Esto funciona creando una proyección de tipo en un tipo parametrizado λ dentro de un tipo estructural, capturando así el parámetro de tipo externo (en este caso A).

El otro problema relacionado con la varianza descrita en su respuesta podría resolverse haciendo que el parámetro Res en Access sea covariante.

Después de estos cambios el código debería tener este aspecto:

trait Access[+Res[_]] { def access[C] : Res[C]} 

trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ] 
+0

Gracias, que se ve un poco mejor. También dado que en mi caso real los parámetros de tipo de CList tenían límites superiores, tener un rasgo dedicado Partial2 no era realmente útil (necesitaría agregar parámetros de tipos para los límites, etc.) –

+0

También si el tipo lambdas se usa con frecuencia en su código, considere el siguiente complemento del compilador: https://github.com/non/kind-projector –

2

google para "aplicación de tipo parcial" He encontrado esta solución publicado por James Iry en la lista Scala debate (http://scala-programming-language.1934581.n4.nabble.com/Partial-type-inference-td2007311.html; adaptada por lo que el orden arg se cambia):

type Partial2[T[_,_], B] = { 
    type Apply[A] = T[A,B] 
} 
trait CList[C1, A] extends Access[Partial2[CList, A]#Apply] 

Louise queso, es esta realmente la única forma de hacerlo en Scala en 2011? !!

EDIT:

Esta falla con covarianza en A:.., - (

trait Access[Res[_]] { def access[C]: Res[C] } 

type Partial2[T[_,_], B] = { 
    type Apply[A] = T[A,B] 
} 
trait CList[C1, +A] extends Access[Partial2[CList, A]#Apply] 

"covariant type A occurs in invariant position" 
0

Sé que esto es una pregunta muy viejo, pero de todos modos:

trait AnyAccess { 
    type Res[X] 
    def access[Z]: Res[Z] 
} 

trait AnyCList extends AnyAccess { me => 
    type C 
    type A 
    // this could be a subtype bound instead, if needed 
    type Res[X] = AnyCList { type C = X; type A = me.A } 
} 
case object AnyCList { 
    type of[C0, +A0] = AnyCList { type C = C0; type A <: A0 } 
} 

case object buh { 

    def test[C1, C2, A](c: AnyCList.of[C1, A]): AnyCList.of[C2, A] = c.access[C2] 
} 
Cuestiones relacionadas