Как я могу сопоставить сигнатуру функции, не получая предупреждения компилятора стирания типа в Scala - PullRequest
4 голосов
/ 25 января 2010

Может кто-нибудь переписать этот код, чтобы сделать то же самое, но без предупреждений компилятора, пожалуйста: -

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")
    }

  }
}

Тысяча благодарностей

Keith

Обновление !!!!. Извините, что сделал настоящий хэш этого. Это мой первый вопрос о SO

Просто чтобы сообщить гуру, что я попробовал что-то в этом роде, также безрезультатно: - (Не могу скомпилировать)

object TestTypeErasure {  

    def doTest(parameter: Any) = {  
        parameter match {  
            case function:Function1[_, _] => function("Whatever")  
        }  
    }  

    def main(args:Array[String]) {  
    }  

}  

Я получаю ошибку: -

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

Еще раз спасибо

Кит

Ответы [ 3 ]

3 голосов
/ 25 января 2010

Вы можете получить информацию о типе с помощью манифестов. (T, R инвариантны здесь для простоты.)

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 

Для Scala 2.8 можно использовать границы контекста, удаляя два неявных параметра:

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)
}
0 голосов
/ 25 января 2010

Существует множество подходов, которые могут сработать, но ни один из них не так прост.

Один из вариантов - использовать манифесты, но вам придется определить свой собственный вариант соответствия, который был манифестом.осознанный.Вы можете прочитать больше о манифестах здесь .Если вам придется много делать такого рода вещи, то это будет путь, хотя эта функция все еще считается экспериментальной.

Другой вариант, если вы используете относительно легковес, - это обернутьфункция в некотором классе, который не является общим.Например,

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)

Если вы упаковываете несколько различных функций, но не слишком много из них, вы можете создать базовый класс WrappedFunction, а затем иметь такие вещи, как AnyImpliesBoolean extension WrappedFunction.

Покадругой вариант - на самом деле не передавать функции, а использовать отражение для передачи java.lang.Methods.Методы знают свои типы.Даже с некоторыми симпатичными оболочками Scala, это все равно будет немного неуклюжим (и не высокопроизводительным).

(Отредактировано, чтобы добавить ссылку на манифест, которую я пропустил.)

0 голосов
/ 25 января 2010
...