Stefano
Stefano

Reputation: 113

Passing Scala Object/companion object as parametric type

I'd like to have a method like this:

def foo[O] = O(1,2,3)

Where "O" would be a scala object with a defined apply method. With my signature, I got the "Cannot resolve symbol O" error.

Calling foo passing a "Set" or a "List" as parameter gives me the "Type XXX takes type parameter". What's the way to pass a companion object as a parametric type?

How can I create this method?

Upvotes: 2

Views: 1552

Answers (2)

Vitruvie
Vitruvie

Reputation: 2327

Pass the apply method (the thing that is called when you say List(1, 2, 3)) as an argument instead:

def foo[O](apply: (Int*) => O): O = apply(1, 2, 3)

println(foo(List.apply))
->  
List(1, 2, 3)

Or, if you really want to pass in the companion object of a Collection class (though this is less versatile than the above solution), you can pass in GenericCompanion objects such as the List companion:

def foo[O[T] <: GenTraversable[T]](comp: GenericCompanion[O]): O[Int] = comp(1, 2, 3)

println(foo(List))
->  
List(1, 2, 3)

Note that this requires higher-kinded types to be enabled in the compiler.

Or, rather than passing in the companion object, you can use an implicit CanBuildFrom (these are defined for you for all collections):

def foo[O[_]](implicit bf: CanBuildFrom[O[_], Int, O[_]]): O[Int] = 
  bf().++=(Seq(1, 2, 3)).result().asInstanceOf[O[Int]]

println(foo[List])
->  
List(1, 2, 3)

Upvotes: 5

Jon Anderson
Jon Anderson

Reputation: 696

The type of a companion object is referenced using the .type property. If you want to create a list of companion objects, the following would work:

object MyObject {
  def apply():Unit = {
    println("Hello, world")
  }
}

val c = List[MyObject.type](MyObject, MyObject)
c.foreach(_.apply())

Upvotes: -1

Related Questions