Scala - type of collection created by cons operators

Multi tool use
Scala - type of collection created by cons operators
What is the type of collection created by cons operator?
1::2::Nil
// println((1::2::Nil).getClass)
// class scala.collection.immutable.$colon$colon
"abc"::1::2::Nil
// println(("abc"::1::2::Nil).getClass)
// class scala.collection.immutable.$colon$colon
val x:List[Int] = 1::2::Nil
// println(x.getClass)
// class scala.collection.immutable.$colon$colon
This makes it seem that lists can contain both string and Int at the same time.
However, this has been specifically called out in "Programming in Scala", that list contains homogeneous objects.
Like lists, tuples are immutable, but unlike lists, tuples can contain
different types of elements. Whereas a list might be a List[Int] or a
List[String], a tuple could contain both an integer and a string at
the same time.
I think at runtime, we see the same types due to type erasure. If that's true, then what is the correct type of the list/collection generated using cons operator?
2 Answers
2
You can check out the signature of the ::
(cons) method:
::
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
It means, you can prepend any B
as long as B
is a supertype of A
(current type of List elements), and the resulting list will have all elements typed as B
. So Scala will pick the most common supertype. In this particular case it's gonna be Any
, which is Scala's root type (similar to Object
in Java). If you have a more specific common supertype, Scala will try hard to use it instead of Any
:
B
B
A
B
Any
Object
Any
> class Animal
> class Cat extends Animal
> class Dog extends Animal
> new Cat :: new Cat :: Nil
res3: List[Cat] = List(ammonite.$sess.cmd1$Cat@2b974137, ammonite.$sess.cmd1$Cat@71734463)
> new Dog :: res3
res4: List[Animal] = List(ammonite.$sess.cmd2$Dog@79f3f34c, ammonite.$sess.cmd1$Cat@2b974137, ammonite.$sess.cmd1$Cat@71734463)
Scala has something called "subytping". The element type of the list will be a common supertype of all the individual element types.
In your first case, the inferred type will be List[Int]
, in your second case List[Any]
. It is perfectly legal for both an Int
and a String
to be elements of a List[Any]
, since both are subtypes of Any
(in fact, every type is a subtype of Any
, because Any
is the top type).
List[Int]
List[Any]
Int
String
List[Any]
Any
Any
Any
In other words: all elements in your second example are of the same type. They are all of type Any
.
Any
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Ahh.. That makes sense. Scala's type inference is able to find the most common supertype here. Since a new list is being created, we are not constrained with subtypes of the original list's type.
– kaustubh
Jun 30 at 16:27