6
votes

In Scala 2.11.2, the following minimal example compiles only when using type ascription on the Array[String]:

object Foo {    

  def fromList(list: List[String]): Foo = new Foo(list.toArray : Array[String])   

}

class Foo(source: IndexedSeq[String])    

If I remove the type ascription in fromList, it will fail to compile with the following error:

Error:(48, 56) polymorphic expression cannot be instantiated to expected type;
 found   : [B >: String]Array[B]
 required: IndexedSeq[String]
  def fromList(list: List[String]): Foo = new Foo(list.toArray)
                                                       ^

Why can't the compiler infer the Array[String] here? Or does this issue have to do something with the implicit conversion from Array's to IndexedSeq's?

1
Note I think you can do: object Foo { def fromList(list: List[String]): Foo = new Foo(list.toArray[String])} instead.Dave L.
Or just list.toIndexedSeq, of course. The question's still a good one, though.Travis Brown
Thanks for pointing that out. The reason I'm going for Arrays instead of IndexedSeqs is purely for performance reasons. I had to profile the function and found that Vectors take more overhead when creating lots of small instances.Chris

1 Answers

4
votes

The issue is that the .toArray method returns an Array of some type B which is a superclass of the T in List[T]. This allows you to use a list.toArray on List[Bar] where an Array[Foo] is required if Bar extends Foo.

Yes, the real reason this doesn't work out of the box is that the compiler is trying to figure out which B to use and also how to get to an IndexedSeq. It seems like it's trying to resolve the IndexedSeq[String] requirement but B is only guaranteed to be a String or a superclass of String; hence the error.

This is my preferred work around:

def fromList(list: List[String]): Foo = new Foo(list.toArray[String])