How can I match a function signature without receiving a warning about the type erase compiler in Scala

Can anyone rewrite this code to do the same, but without any compiler warnings, please: -

object TestTypeErasure { def main(args:Array[String]) { def myFunction(myObject:Any):Boolean = { true } val myVariable: (Any => Boolean) = myFunction myVariable match { case function:(Any => Boolean) => println("Match") } } } 

Thousand thanks

Whale

Update !!!!. Sorry to do a real hash of this. His first question is about SO

Just so that the gurus know that I have tried something about this, also to no avail: - (Unable to compile it)

 object TestTypeErasure { def doTest(parameter: Any) = { parameter match { case function:Function1[_, _] => function("Whatever") } } def main(args:Array[String]) { } } 

I get an error: -

 TestTypeErasure.scala:6: error: type mismatch; found : java.lang.String("Whatever") required: _ case function:Function1[_, _] => function("Whatever") ^ one error found 

Thanks again

Keith

+4
source share
3 answers

You can record type information using Manifests. (T, R are invariant here so that everything is simple.)

 import scala.reflect._ def matchFunction[T,R](f: Function1[T,R], t : T)(implicit mt : Manifest[T], mr : Manifest[R]) = { val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t) else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t) else "Unknown " + f(t) println(result) } scala> matchFunction((x : Int) => x + 1, 1) int, int 2 scala> matchFunction((x : Any) => true, 1 : Any) any, boolean true scala> matchFunction((x : Boolean) => ! x, false) Unknown 

For Scala 2.8, you can use context boundaries by removing two implicit parameters:

 import scala.reflect._ def matchFunction[T: Manifest,R : Manifest](f: Function1[T,R], t : T) = { val mt = implicitly[Manifest[T]] val mr = implicitly[Manifest[T]] val result = if ((mt.erasure, mr.erasure) == (classOf[Any], classOf[Boolean])) "any, boolean " + f(t) else if((mt.erasure, mr.erasure) == (classOf[Int], classOf[Int])) "int, int " + f(t) else "Unknown " + f(t) println(result) } 
+3
source

There are many approaches that can work, none of which are simple.

One option is to use manifests, but you will need to define your own matching variant that was recognized by the manifest. Read more about manifests here . If you need to do a lot of things, this will be the way to go, although this function is still considered experimental.

Another option, if your use is relatively lightweight, is to wrap the function in some class that is not shared. For instance,

 object Example { def hasString(a:Any) = (a!=null && a.toString.length>0) case class AnyImpliesBoolean(f: (Any) => Boolean) { } implicit def callAIB(aib: AnyImpliesBoolean) = aib.f def callWrapped(a: Any) { a match { case aib: AnyImpliesBoolean => println( aib("Check") ) case _ => println("(Nothing)") } } def tryMe() { val has = AnyImpliesBoolean(hasString _) callWrapped( has ) callWrapped("foo") callWrapped((s:String)=>true) } } scala> Example.tryMe true (Nothing) (Nothing) 

If you wrap several different functions, but not too many of them, you can create a WrappedFunction base class and then have things like AnyImpliesBoolean, extend the WrappedFunction.

Another option is to actually not pass functions around, but instead use reflection to pass java.lang.Methods. Methods know their types. Even with some beautiful Scala packers, it will still be a little awkward (and it's not high performing).

(Edited to add a manifest link that I was not in.)

0
source

Source: https://habr.com/ru/post/1299329/


All Articles