2011-05-09 21 views
5

Soy bastante nuevo en Scala y en lenguajes de programación avanzados. Intento resolver el siguiente problema.Extracción de tipo en Scala

que han conseguido:

val s: Seq[SomeMutableType[_]] 

que asumen que todos los elementos de la secuencia son del mismo tipo (pero no sabe cuál en este punto).

¿En qué puedo llamar:

def proc[T](v0: SomeMutableType[T], v1: SomeMutableType[T]) { /* ... */ } 

con algo como

proc(s(0), s(1)) 

El compilador se queja:

  • coincidencia de tipos; found: SomeMutableType [_ $ 351] donde type _ $ 351 required: SomeMutableType [Any] Nota: _ $ 351 <: Cualquiera, pero la clase SomeMutableType es invariable en el tipo T. Es posible que desee definir T como + T. (SLS 4,5)

pensé en esa cosa covariante, pero no creo que tiene sentido en mi caso. Solo quiero que el compilador me crea cuando digo que s (0) y s (1) son del mismo tipo. Normalmente hago esto a través de un casting, pero no puedo convertir a SomeMutableType [T] aquí ya que T es desconocido debido a borrado. Por supuesto, no puedo cambiar la definición de proc.

+1

¿Cómo se obtiene 's'? Idealmente, debe unir su '_' a algún parámetro de tipo declarado en un método o clase ... –

+0

En realidad, es bastante complicado. SomeMutableType está parametrizado porque hace sens para parametrizarlo. Sin embargo, s es un atributo de una clase C que generalmente no se preocupa por el parámetro, excepto en mi caso de uso particular (donde todos los elementos deben ser del mismo tipo). Puedo suponer que en mi instancia de C, todos los elementos de s son del mismo tipo, pero no es cierto en el caso general. Quizás debería usar alguna subclase de C en este punto, pero haría que algún otro código sea bastante complicado (introduzca métodos de fábrica, etc.), ya que las clases las genera un analizador. – scand1sk

+0

"No hice un seguimiento del tipo, pero sé que es X". - luego, vuélvela a X y manifiesta tu suposición en el código. Si no quieres lanzar, debes TENER un seguimiento del tipo. ¡Es así de simple! – ziggystar

Respuesta

1

Soy nuevo en Scala, pero por lo que puedo ver su problema es el uso de un parámetro de tipo comodín cuando se declara s:

val s: Seq[SomeMutableType[_]] 

Por lo que yo entiendo, el tipo de borrado sucederá siempre y lo que realmente quiere aquí es un tipo parametrizado vinculado a donde s se inicializa.

Por ejemplo:

scala> class Erased(val s: List[_]) 
defined class Erased 

scala> new Erased(List(1,2,3)).s.head 
res21: Any = 1 

Si en lugar de utilizar

scala> class Kept[T](val s: List[T]) 
defined class Kept 

scala> new Kept(List(1,2,3)).s.head 
res22: Int = 1 

A continuación, el contenido de s mantienen su información de tipo al que le obligan a T. Es decir, este es exactamente como se indica al compilador "que s (0) y s (1) son del mismo tipo".

4

El problema es que realmente no puede hacer esa garantía. Por ejemplo:

scala> import scala.collection.mutable.Buffer 
import scala.collection.mutable.Buffer 

scala> val s: Seq[Buffer[_]] = Seq(Buffer(1), Buffer("a")) 
s: Seq[scala.collection.mutable.Buffer[_]] = List(ArrayBuffer(1), ArrayBuffer(a)) 

Ver? Usted no sabe sabe que s(0) y s(1) son del mismo tipo, porque pueden no ser del mismo tipo.

En este punto, debe hacer una pregunta acerca de lo que quiere lograr, en lugar de preguntar cómo resolver un problema en cómo desea lograrlo. La forma en que tomaste no funcionará. Retroceda, piense qué problema estaba tratando de resolver con este enfoque y pregúntele cómo resolver ese problema.

Por ejemplo, dicen:

Asumo que todos los elementos de la secuencia son del mismo tipo (pero no saben lo que uno en este punto).

Es posible que lo que quiera hacer sea parametrizar una clase o método, y use su parámetro de tipo al declarar s. O, tal vez, no tener un s en absoluto.

+0

Sé que no "sé" que s (0) y s (1) son del mismo tipo, pero me gustaría tener algún 'ClassCastException' o algún equivalente si no fuera así cuando llame 'proc'. El parámetro de tipo de mi 'SomeMutableType' es útil en algunas partes de mi aplicación, pero realmente no me importa aquí. – scand1sk

+0

Lo que estoy tratando de hacer aquí es modelar un hipergraph: 'SomeMutableType' son nodos que encapsulan un conjunto de valores tipeados. 's' es una secuencia de nodos enlazados por el hyperedge. De acuerdo con algunas propiedades (que difícilmente se pueden calcular cuando se crea el hyperedge), puedo fusionar todos los nodos de un hyperedge determinado en un nodo elegido y descartar el hyperedge. Los valores de ese nodo único se reducen a la intersección de los conjuntos encapsulados por todos los nodos. El método que calcula la intersección asume que todos los valores son del mismo tipo, por lo tanto, mi problema ... – scand1sk

+1

@ scand1sk ¿Por qué no lo convierte en 'Seq [SomeMutableType [AnyRef]]', entonces? O bien, si conoce el tipo en el momento en que realiza esta llamada, use 'collect' para generar una colección de tipo conocido. –