Seny's decision is great. Unfortunately, as he said, this will not work for Map and String . Here is another alternative (based on its solution) that does:
import collection.generic.CanBuildFrom import collection.breakOut class Build[To] def build[TargetSuperType] = new Build[TargetSuperType] implicit def buildToCbf[From, T, TargetSuperType, To<:TargetSuperType](b: Build[TargetSuperType]) (implicit cbf: CanBuildFrom[Nothing,T,To]): CanBuildFrom[From,T,To] = collection.breakOut List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(build[Array[_]]) //res0: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3)) List(1, 2, 3).map{i => (i * 2, i.toString)}(build[Map[_,_]]) //res1: scala.collection.immutable.Map[Int,String] = Map(2 -> 1, 4 -> 2, 6 -> 3) List('a', 'b', 'c').map(_.toUpper)(build[String]) //res2: String = ABC
This is a bit more detailed, because now you are not just build[Array] , but build[Array[_]] . In return, you get the opportunity to specify any target collection that you want, regardless of the number of type arguments (for example, Map and String ).
In addition, you can be completely explicit (similar to using breakOut ) if you decide:
scala> List(1, 2, 3).map{i => (i * 2, i / 2.0, i.toString)}(build[Array[(Int, Double, String)]]) res3: Array[(Int, Double, String)] = Array((2,0.5,1), (4,1.0,2), (6,1.5,3))
Everything with the same syntax (in other words, using the same build name as you requested)