4
votes

I have some code similar to the following, where I have a function that takes a List[TypeA], and I want to be able to call it with a List[TypeB], where I have an implicit conversion from TypeA to TypeB.

I have some sample code which works when I call the method with the List inline, but doesn't work if the list is assigned to a variable first.

Here's some code that works:

class Person(val name: String)
implicit def stringToPerson(str: String) : Person = new Person(str)

def printAll(list: List[Person]) {
  list.foreach(person => println("Person: " + person.name))
}

def callIt = {
  printAll(List("1","2","3"))
}

Unfortunately it doesn't work if callIt looks like this:

def callIt = {
  val list = List("1","2","3")
  printAll(list)
}

I get the error that it expects a List[Person] but I'm giving a List[String]

In my actual code, I have the list already defined somewhere else, so it doesn't end up working. What can I do to make it use the implicit conversion from String to Person, and why does it work in the first case but not the second?

Side note: it also works if I specify the type of list and have it do the conversion then:

val list: List[Person] = List("1","2","3")

But again, that's not what I want.

Do I really need to provide an implicit conversion from List[String] to List[Person]?

1
you should define the method printAll as: def printAll[T <% Person](ls: List[T]) = {}Eastsun

1 Answers

4
votes

The reason your initial code works is because in printAll(List("1","2","3")) the compiler uses type inference to know that Person is needed before it constructs the List. That line tells the compiler it needs a List[Person] which then forces the call to List() to be returning a List[Person] which forces the parameters of that call to be Person which then forces the use of an implicit conversion from String to Person. Unfortunately the statement val list = List("1","2","3") says nothing about needing to be of type List[Person]