2011-03-25 6 views
9

Intuitivamente la siguiente debería funcionar:Sec configurar y volver a Sec

case class I(i: Int) 
val s = Seq(I(1),I(2),I(3)) 
s.sortBy(_.i)    // works 
s.toSeq.sortBy(_.i)  // works 
s.toSet.toSeq.sortBy(_.i) // doesn´t work 

Por qué Indiferente se comporta como se esperaba?

Respuesta

15

Este es un efecto complicado de mezclar covariantes y colecciones invariantes. El conjunto es invariante: Set[A]. Pero Seq es covariante: Seq[+A]. Ahora, imagina que quieres tener un método toSet en tu Seq. Puede intentar toSet: Set[A]. Pero esto no va a funcionar, porque si A es una subclase de B, entonces Seq[A] se debe considerar como una subclase de Seq[B]. Sin embargo, Seq[A] insiste en devolver un Set[A] que es no una subclase de Seq[B]. Entonces nuestra escritura está rota.

Si, por el contrario, especificamos toSeq[B >: A]: Set[B] entonces todo está bien: si prometemos que puede devolver cualquier superclase, entonces puede regresar Seq[A]Set[B], así como Set[C] donde C es una superclase de B. Seq[B] prometió devolver Set[B] o algunos Set[C] también, así que estamos en claro: el método en Seq[A] puede hacer todo lo que el método en Seq[B] puede hacer.

Pero ahora un vistazo a lo que los pobres Typer se enfrenta a:

s.toSet[B >: I] 
.toSeq/* Type B >: I*/ 
.sortBy[C](/* some f:B => C */)(/* implicit ordering on C */) 

Hay es una manera de resolver esto - es decir, a decidir que es BI y escriba la función y C en consecuencia. Pero se convierte en una búsqueda bastante complicada, y es más de lo que el compilador puede manejar en este momento. Por lo tanto, le pedirá que lo ayude con el tipo de entrada a la función para que sepa B en ese punto (y luego puede propagarlo de nuevo al toSet).

Pero se puede, si lo desea, ayudarla a salir en una serie de niveles:

s.toSet[I].toSeq.sortBy(_.i) 
s.toSet.toSeq.sortBy[Int](_.i) 

o se lo puede ayudar a cabo mediante la demostración de que que no es necesario tener en cuenta los tipos posteriores al momento de retirar el mejor partido con tipos anteriores:

{ val temp = s.toSet; temp }.toSeq.sortBy(_.i) 
s.toSet match { case x => x.toSeq.sortBy(_.i) } 
+0

Rex, gracias por esa iluminación, eso es lo que quería. Tales respuestas no solo resuelven el problema, sino que también me ayudan a entender mejor lo que está sucediendo. ¡Muchas gracias! Qué lástima, uno solo puede votar una vez: D –

0

Parece que tiene algo que ver con la inferencia de tipo, no lo sé muy bien.

Pero ambos siguiente hace el truco:

+0

Sí, sé cómo superar el problema, pero ¿por qué persiste en mi caso? No es intuitivamente –

Cuestiones relacionadas