5

Stavo cercando di definire un tipo che accetta un tipo di tipo superiore di tipo esistenziale in Scala.Come definire un tipo di tipo superiore di tipo esistenziale in Scala

Sfortunatamente Scalac non lo consente.

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

trait H[F[_, _]] 
trait T[A, B] 
val h:H[T] = null 
val e:H[F] forSome { type F[A, B] } = h 

// Exiting paste mode, now interpreting. 

<console>:13: error: type mismatch; 
found : H[T] 
required: H[_[A, B] <: Any] 
Note: T <: Any, but trait H is invariant in type F. 
You may wish to define F as +F instead. (SLS 4.5) 
     val e:H[F] forSome { type F[A, B] } = h 
              ^

Come posso aggirarlo?

Come è possibile definire un tipo che corrisponde a qualsiasi H indipendentemente dal parametro di tipo?

Aggiornamento: ho persino provato a far dedurre da Scalac il tipo esistenziale, ancora non fortunato.

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> :paste 
// Entering paste mode (ctrl-D to finish) 

trait H[F[_, _]] 
trait T[A, B] 
val h:H[T] = null 
trait T2[A, B] 
val h2:H[T2] = null 
Seq(h, h2) 

// Exiting paste mode, now interpreting. 

<console>:17: error: type mismatch; 
found : H[T] 
required: H[_ >: T2 with T <: Object] 
     Seq(h, h2) 
     ^
<console>:17: error: type mismatch; 
found : H[T2] 
required: H[_ >: T2 with T <: Object] 
     Seq(h, h2) 
      ^
+0

io non credo che si possa. Vedi http://stackoverflow.com/questions/3122398/cant-existentially-abstract-over-parameterized-type – sschaef

+0

Ecco la cosa strana: rendere 'H' covariante in' F' ('tratto H [+ F [_, _ ]]) e all'improvviso compila bene: 'val h2: H [Any] = null'. Sì, c'è "Any" proprio lì, dove è previsto un costruttore di tipo ** **. Se qualcuno sa se è intenzionale (e se sì, qual è il significato) mi piacerebbe sapere. –

+0

@ RégisJean-Gilles Immagino sia un errore di scalac –

risposta

0

Probabilmente sschaef ha ragione, questo non è possibile. Non so se la seguente ti aiuta in alcun modo:

type F[A,B] = X[A,B] forSome { type X[A,B] } // alias 

trait H[F[_, _]] 
trait T[A, B] 
val h: H[T] = null 

val e: H[F] = h.asInstanceOf[H[F]] 
0

ho scoperto che esistenziali tipi di alto-kinded possono essere scritti in modelli di tipo (e desunti da lì):

def toExistential[F[_, _]](h: H[F]) = h.asInstanceOf[Any] match { 
    case x: H[_] => x 
} 

> val h = new H[T] {} 
h: H[T] = [email protected] 
> val f = toExistential(h) 
f: H[_] = [email protected] 

Il cast to Any sembra essere necessario, ma almeno può essere incapsulato in una funzione.

0

Invece di un parametro di tipo si potrebbe usare un membro di tipo:

trait H { 
    type F[_, _] 
}