Reputation: 11
I am getting this error while trying to filter "records" kept in a List. I am supposed to get a List[Map[String, String]] which will have all companies with their HQ locations.
non-variable type argument String in type pattern scala.collection.immutable.Map[String,String] (the underlying of Map[String,String]) is unchecked since it is eliminated by erasure
case map: Map[String, String] if map.contains("company") => new Some(Company(map.get("company").get, map.get("origin").get))
I am just learning scala and I am not sure what to do, so that the type won't be lost during runtime
object Main {
def main(args: Array[String]): Unit = {
val data = List(
Map("name" -> "Jan", "fname" -> "Kowalski", "age" -> "45"),
Map("company" -> "ABB", "origin" -> "Sweden"),
Map("name" -> "Katarzyna", "fname" -> "Nowak", "age" -> "45"), Map("company" -> "F4", "origin" -> "Poland"),
List("Cos", "innego"),
Map("company" -> "Salina Bochnia", "origin" -> "Poland"),
Map("company" -> "AGH", "origin" -> "Poland"),
Map("name" -> "Krzysztof", "fname" -> "Krol", "age" -> "14")
)
getCompanies(data)
}
def getCompanies(toFilter: List[Any]): List[Any] ={
val result = for(record <- toFilter) yield filterRecords(record)
result.toList.filter(_ != None)
}
def filterRecords(record: Any): Option[Company] ={
record match{
case map: Map[String, String] if map.contains("company") => new Some(Company(map.get("company").get, map.get("origin").get))
case _ => None
}
}
}
case class Company (name: String, origin: String)
Upvotes: 1
Views: 1632
Reputation: 3173
First, there are many resources about what type erasure is, why it happens and so on, so I wouldn't explain it here. Try better "typing", in your scenario, your data consists of either List[String]
or Map[String, String]
, in Scala3 you can easily deal with it using Union Types, but a better solution would be to put restrictions on your input data and try wrapping them into something you would know about, in compile time. like this:
trait ListElement // can also be sealed, depends on what you have
case class ListHolder(value: List[String]) extends ListElement
case class MapHolder(value: Map[String, String]) extends ListElement
I would also create a companion object for the trait, for easier object creation:
object ListElement {
def apply(arg: List[String]): ListElement = ListHolder(arg)
def apply(arg: Map[String, String]): ListElement = MapHolder(arg)
}
Now let's re-create your data:
val data: List[ListElement] = List(
ListElement(Map("name" -> "Jan", "fname" -> "Kowalski", "age" -> "45")),
ListElement(List("Cos", "innego")),
// ... other data here
)
Now I would rewrite your functions as follows, have better typing, are easier to track and safer:
def filterRecord(record: ListElement): Option[Company] = record match {
case MapHolder(myMap) => myMap.get("company").map { companyName =>
Company(
companyName,
myMap.get("origin").get // PLEASE do not use .get, .getOrElse would be safer
)
}
case _ => None
}
def getCompanies(toFilter: List[ListElement]): List[Company] =
toFilter.map(filterRecord).collect {
case Some(company) => company
}
Upvotes: 1