2011-04-03 1 views
12

sto cercando disperatamente di risolvere il seguente:Parzialmente applicando parametri di 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 dice solo: "error: illegal cyclic reference involving trait CList". come posso compilare questo?

risposta

13

Potreste essere interessati a tipo lambda L'applicazione parziale si è utilizzato nella vostra risposta è in realtà implemented in scalaz Poiché il codice tende ad essere meno leggibile, tuttavia, hanno iniziato a utilizzare il tipo lambdas.Il tipo in questione potrebbe essere scritto come

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

Questo funziona creando una proiezione di tipo su un tipo parametrizzato λ all'interno di un tipo strutturale, acquisendo così il parametro di tipo esterno (in questo caso A).

L'altro problema relativo alla varianza descritto nella risposta potrebbe essere risolto impostando il parametro Res nella covariant Access.

Dopo queste modifiche il codice dovrebbe apparire così:

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

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

Grazie, che sembra un po 'meglio. Anche perché nel mio caso reale i parametri di tipo di CList avevano limiti superiori, avendo un carattere dedicato Partial2 non era molto utile (avrei bisogno di aggiungere parametri tipo per i limiti ecc.) –

+0

Anche se i tipi lambda sono usati spesso nel tuo codice, considera il seguente plug-in del compilatore: https://github.com/non/kind-projector –

2

googling per "tipo di applicazione parziale" Ho trovato questa soluzione inviato da James Iry sulla lista dibattito Scala (http://scala-programming-language.1934581.n4.nabble.com/Partial-type-inference-td2007311.html, adattato in modo da l'ordine arg viene modificato):

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

Louise formaggio, è davvero questo il l'unico modo per farlo in scala nel 2011? !!

EDIT:

Questo viene a mancare con covarianza in 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

So che questa è una domanda molto vecchio, ma in ogni caso:

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