Finding the type of a list : isIstance of a list

Dear Scala Users,

In a project dealing with algebraic data types in Scala, I am trying to decide whether an object is an instance of a given class. However, I am facing a strange problem with lists.

For instance, if I try to determine whether List[Double](1.1, 4.2) is an instance of classOf[List[Int]], using the isInstance method, I got true (but it is obviously false…):

scala> classOf[List[Int]].isInstance(List[Double](1.1, 4.2))
val res: Boolean = true

Does anyone know how to explain this strange result ?

Thank you in advance for your answers,
Best,

Loïc

Because isInstanceOf checks for classes not types (which are not the same), and due type erasure in runtime there is only List.

That is why any kind of runtime type testing is prohibited (except for ADTs).

You should redesign your problem so you do not need to do this. Can you share more about why you end up using isInstanceOf?

Thanks a lot for your answer !

I thought that it was due to type erasure too…
Also I am using isInstance and not isIstanceOf. I know it is not a usual thing, but is it possible to know at runtime that a given list is a List[Int] or a List[Double] ?

For a research project, I am building a type system in Scala, in which type calculus can be done (unions, intersections…). In my type system, a “type” has to be considered as a subset of all objects that can live in runtime. Hence, in this type system I want to be able to express native Scala types. For example, being able to check wether x belongs to the type composed by all Scala integers. Or, in this example, wether a given list l belongs to the set of the lists composed by integers, List[Int]. That is precisely why I am using isInstance method.

Also I am using isInstance and not isIstanceOf .

Ah sorry, I was on mobile and didn’t see that.
But then again, that is some kind of runtime “type” (actually class) testing.

I believe that you may do the same thing the compiler does, create a new type for each possible combination. Not sure how the compile actually manages this, but a naive approach would be something like:

sealed trait Type
final case object Int extends Type
...
final case class List(type: Type) extends Type

It isn’t. The type is erased. Type erasure doesn’t mean the type is just, like, hidden away somewhere and you have to do a little extra dance to get to it. It is erased, it is GONE, it no longer exists, it has joined the choir invisible. This is true in both Java and Scala.

In the case of Scala’s immutable collections like scala.collection.immutable.List the situation is even more extreme — the empty List[Int] and the empty List[Double] are literally one and the same value:

scala 2.13.3> List[Double]() eq List[Int]()
val res0: Boolean = true

note the eq, which tests for reference equality.

1 Like

Ok, thank you very much for your lightening answers ! :slight_smile:

Thank you !

I understand more precisely the problem, thanks a lot ! :slight_smile:

1 Like