I would like to pattern match a function, the problem is type erasure. Notice how in the snippet below, despite the warning issued a match occurs and a "wrong" one at that.
scala> def f1 = ()=>true
f1: () => Boolean
scala> val fl = f1
fl: () => Boolean = <function0>
scala>
scala> fl match {
| case fp :Function0[Boolean] => 1
| case _ => 2
| }
res8: Int = 1
scala>
scala> fl match {
| case fp :Function0[String] => 1
| case _ => 2
| }
<console>:11: warning: fruitless type test: a value of type () => Boolean cannot also be a () => String (but still might match its erasure)
case fp :Function0[String] => 1
^
res9: Int = 1
scala>
What I could come up with is a case class wrapping up the function. I get type safety, notice the error below. But, this is, first, inelegant and second, I don't understand how the case class can enforce types whereas the pattern match can't. The only guess I would have is that the case class is protected by the compiler and that the match is only resolved against during runtime
scala> case class FunctionWrapper(fn: ()=>Boolean)
defined class FunctionWrapper
scala> val fw = FunctionWrapper(fl)
fw: FunctionWrapper = FunctionWrapper(<function0>)
scala> def fs = ()=>"whatever"
fs: () => String
scala> val fws = FunctionWrapper(fs)
<console>:10: error: type mismatch;
found : () => String
required: () => Boolean
val fws = FunctionWrapper(fs)
^
scala> fw match {
| case FunctionWrapper(f) => f()
| case _ => false
| }
res10: Boolean = true
To sum up, I would like to know if there is an elegant way to pattern match a function, and perhaps understand why the examples above acted as they did