5

Hai problemi con il tipo di "tipi":tipi non conformi con il tipo di lambda

trait Sys[ S <: Sys[S]] 
trait Expr[S <: Sys[S], A] 
trait Attr[S <: Sys[S], A[_]] 
def test[ S <: Sys[S]]: Attr[S, ({type l[x<:Sys[x]]=Expr[x,Int]})#l] = ??? 

Questo viene a mancare con

error: kinds of the type arguments (S,[x <: Sys[x]]Expr[x,Int]) do not conform 
to the expected kinds of the type parameters (type S,type A) in trait Attr. 
[x <: Sys[x]]Expr[x,Int]'s type parameters do not match type A's expected parameters: 
type x's bounds <: Sys[x] are stricter than type _'s declared bounds >: Nothing <: Any 
      def test[S <: Sys[S]]: Attr[S, ({type l[x<:Sys[x]]=Expr[x,Int]})#l] = ??? 
           ^

Qual è il problema con i limiti dichiarati? Devo portare quel tipo parzialmente applicato in cr * ppy nel costruttore del tipo di trait Attr? E perché? Posso risolvere questo problema senza toccare la definizione di Attr?

ho bisogno i limiti in funzione test in modo che l'attuazione di lavorare, ma io non vuole proliferare questi limiti per l'interfaccia pubblica Attr.


Nota: Se io uso un tipo di membro (ciò che non voglio), funziona:

trait Attr[S <: Sys[S]] { type A[_]} 
def test[ S <: Sys[S]]: Attr[S] { type A[S <: Sys[S]] = Expr[S, Int]} = ??? 

risposta

4

Come si osserva, non si può sempre mancata corrispondenza limiti quando fornendo un argomento di tipo più elevato. È interessante notare che, in realtà è una questione di varianza:

class A 
class B extends A 
trait NeedsNeedsA[T[S <: A]] 
trait NeedsNeedsB[T[S <: B]] 
trait NeedsA[S <: A] 
trait NeedsB[S <: B] 

def x: NeedsNeedsA[NeedsB] // fails 
def y: NeedsNeedsB[NeedsA] // works 

che ha un senso se si pensa di un tipo superiore kinded in funzione sui tipi, contravariant in di suo argomento legato.

interessante, in un tipo strutturale, che si trova sulla superficie molto simile subtyping, Scala non dà lo stesso errore:

def t: MemberNeedsA { type T[S <: B] } 
def u: MemberNeedsB { type T[S <: A] } 

il motivo è che un tipo strutturale è una specie di un incrocio:

def s: MemberNeedsA with MemberNeedsB 

e può essere che quell'intersezione non può realmente esistere in natura, ma Scala non controlla quello.

OK, ma non è così pertinente alla tua domanda. Torna alla tua domanda: penso che tu abbia un problema di varianza. Si vuole test che invia il chiamante un Attr, ed un Attr posseses una funzione di tipo (A[_]), e si vuole dire, questoAttr ha una funzione di tipo che richiede una più specifica argomento . Penso che tu possa capire perché non dovresti essere autorizzato a farlo - è lo stesso motivo per cui non puoi sostituire una funzione che richiede un argomento più specifico al posto di uno che richiederebbe un argomento più generale.

A questo punto temo che la soluzione dipenda da ciò che si desidera che Attr sia in grado di eseguire. È necessario capire perché è necessario limitare l'argomento del tipo in alcuni casi più di altri. Se ha senso concettuale nel programma che "alcuni Attr s sono più restrittive di altri", è possibile definire:

trait Attr[S <: Sys[S], B[Y <: B[Y]], A[X <: B[X]]] 
def test[S <: Sys[S]]: Attr[S, Sys, L] = ... 

Ma la soluzione dipenderà da ciò che la restrizione della tesi A[_] s' è destinato a significare.

+0

Grazie per l'analisi. Ha senso, anche se "avendo un' A [_] '" mentre ti permette di chiamare il "type constructor" 'A [Any]', non puoi chiamare un costruttore di valori, quindi in termini di runtime questo andrebbe bene IMO. D'altra parte, immagino che potrebbe causare problemi con la meta-programmazione in fase di compilazione utilizzando i vincoli di tipo? Alla fine, la soluzione (almeno per quanto ho usato finora) è semplice. Il sito di utilizzo non può fare molto con 'A [_]' comunque e questa informazione di tipo è più per il chiamante di 'test', così ho sostituito' A1 = A [_] 'in' Attr' e 'test' quindi restituisce' Attr [S, Expr [S, Int]] '. –