Reputation: 1122
I am trying to access a list object inside of another list with a specific type
val x = List ("item1" , "item2" , List ("a","b","c"))
val list_from_x :List [String]= x(2) // producing error
I need my list_from_x
of type to be of List [String]
any idea how to I do such conversion ?
Upvotes: 0
Views: 1468
Reputation: 14380
HList
to the rescue:
import shapeless._
import Nat._
val x = "item1" :: "item2" :: List("a,b,c") :: HNil
val list_from_x = x(_2)
list_from_x
has the type List[String]
See the shapeless github page for more info.
As other answers have mentioned, a List
can only hold elements of a certain type. For example, a List[String]
can only hold String
s. If you put elements of mixed types into a List
, then the parametrised type of the List
will become the most specific type common to all the elements.
The most specific type common to String
and List
is Any
. So in this example, x
is of type List[Any]
:
val x = List("item1" , "item2" , List ("a,b,c"))
HList
can hold elements of different types and maintain each element's type.
Upvotes: 2
Reputation: 31724
The issue is List
is defined as List[+A]
(source). Which means List
takes a type parameter of co-variant type. (You can think of co-variance as type converting from narrow to broader. For ex: if Dog
extends Animal
and if you do Animal a = new Dog()
, you have a Dog (narrow) converting to Animal (broader))
x
is of type List[Object]
. Doing
scala> val x = List ("item1" , "item2" , List ("a,b,c"))
x: List[Object] = List(item1, item2, List(a,b,c))
val list_from_x :List [String]= x(2)
is ultimately converting from List[Object]
(broader) to List[String]
(narrow). Which is contra-variant. Hence the compiler threw error because List is meant to be co-variant.
For ex: the below is completely valid. Thanks to co-variance:
scala> val x = List("hello")
x: List[String] = List(sdf)
scala> val o:List[Object] = x
o: List[Object] = List(sdf)
Upvotes: 0
Reputation: 855
Scala compiler will simply say you got Objects (or may be Any) inside list x. That's why. You have to cast the 3rd element into a List in order to assign into a List variable.
Upvotes: 0
Reputation: 8463
So x
is of type List[Object]
**, because you've used two different (otherwise unrelated) classes as elements of that list.
You'll be unable to access elements other than of type Any
without a type cast:
val listFromX = x(2).asInstanceOf[List[String]]
This is not type-safe, so you'll want to check element types (x(2).isInstanceOf[List[_]]
) or pattern matching.
** Use the REPL to verify this; though val x: List[Any] = List ("item1" , "item2" , List ("a,b,c"))
works
Upvotes: 2