views:

162

answers:

2

Hi, I need to have a collection of generic functions, but I can't get it done in the way I like. I created a

List[(Any)=>Unit]

but as soon as I try to insert a function, for example a

String=>Unit

I get an error. How could I declare a generic function collection that does not consider parameter and return values types?

+11  A: 

Functions are contravariant in the intput type parameters, e.g. in your case Function1[-T1,+R]. This means you can add an instance of Any => Unit to a List[String => Unit] but not the other way round. This of course makes sense as you cannot call a function expecting an argument of type String with an argument of type Any.

Moritz
+8  A: 

Just to finish of @Moritz's answer, you need to choose type argument for T1 that is a subtype of the input type of every function in the list. Nothing fits the bill -- it is a subtype of every type.

scala> val l: List[Nothing => Any] = List((b: String) => b, (a: Int) => a)
l: List[(Nothing) => Any] = List(<function1>, <function1>)

An existential type also works:

scala> val l: List[_ => _] = List((b: String) => b, (a: Int) => a)        
l: List[Function1[_, _]] = List(<function1>, <function1>)
retronym
How would you call a function with the signature `(Nothing)=>Any`?
Ken Bloom
You can't, without a cast. But the question didn't call for that :)
retronym
Is there a way to get dynamically (Maybe through reflection) the actual type of the function, so that I can perform the cast?
mariosangiorgio
At runtime, its the type parameters are erased, it's just a `def apply(v: AnyRef): AnyRef`.
retronym