scand1sk
scand1sk

Reputation: 1124

Type extraction in Scala

I am pretty new to Scala and advanced programming languages. I try to solve the following problem.

I have got:

val s: Seq[SomeMutableType[_]]

I assume that all elements in the sequence are of the same type (but do not know which one at this point).

How may I call :

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

with something like

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

The compiler complains :

  • type mismatch; found : SomeMutableType[_$351] where type _$351 required: SomeMutableType[Any] Note: _$351 <: Any, but class SomeMutableType is invariant in type T. You may wish to define T as +T instead. (SLS 4.5)

I thought about that covariant thing, but I do not believe it makes sense in my case. I just want the compiler believe me when I say that s(0) and s(1) are of the same type! I usually do this via some casting, but I cannot cast to SomeMutableType[T] here since T is unknown due to erasure. Of course, I cannot change the definition of proc.

Upvotes: 5

Views: 591

Answers (2)

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297265

The problem is that you truly cannot make such a guarantee. For example:

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))

See? You don't know that s(0) and s(1) are of the same type, because they may not be of the same type.

At this point, you should ask a question about what you want to accomplish, instead of asking how to solve a problem in how you want to accomplish it. They way you took won't work. Step back, think what problem you were trying to solve with this approach, and ask how to solve that problem.

For instance, you say:

I assume that all elements in the sequence are of the same type (but do not know which one at this point).

It may be that what you want to do is parameterize a class or method, and use its type parameter when declaring s. Or, maybe, not have an s at all.

Upvotes: 4

David McLaughlin
David McLaughlin

Reputation: 5188

I am new to Scala, but as far as I can see your problem is the use of a wildcard type parameter when you declare s:

val s: Seq[SomeMutableType[_]]

As far as I understand, type erasure will always happen and what you really want here is a parameterised type bound to where s is initialised.

For example:

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

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

If instead you use

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

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

Then the contents of s retain their type information as it is bound to T. i.e. This is exactly how you tell the compiler "that s(0) and s(1) are of the same type".

Upvotes: 1

Related Questions