Можем ли мы сопоставить Any с универсальным типом? [Scala 2.8] - PullRequest
5 голосов
/ 01 февраля 2011

Пожалуйста, укажите мне правильную ссылку, если на этот вопрос уже был дан ответ.

У меня есть этот код:

def getResult(a:Any):Any = a

def getAnswer[T](i:Int) = {
  val result = getResult(i)
  result match {
    case t:T => Some(t)
    case _ => None
  }
}

Это дает мне unchecked warning, и все соответствует T,Например, когда я делаю getAnswer[Int](2), я получаю Some(2) (как и ожидалось).Однако, если я сделаю getAnswer[String](2), я также получу Some(2), что не ожидается (мне нужно None).

Есть ли способ обойти удаление типа и каким-то образом заставить getAnswer работать правильно (т. Е. Вернуть Some(result) тогда и только тогда, когда результат имеет тип T)?

Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 01 февраля 2011
def getAnswer[T](i:Any)(implicit m:Manifest[T]) = i match {
    case t:Int if m.erasure == classOf[Int] => Some(t)
    case t:Double if m.erasure == classOf[Double] => Some(t)
    //... other Primitives  
    case t if m.erasure.isInstance(t) => Some(t) //this matches AnyRefs
    case _ => None
}

Как писал Алексей, у вас проблемы с примитивами. Техника, используемая в источниках Scala в таких случаях, включает в себя всегда отдельные совпадения для каждого отдельного типа примитива, так что я думаю, что пути назад нет.

5 голосов
/ 01 февраля 2011

Это работает с некоторыми ограничениями (T должен быть классом, а не примитивным типом; если T является общим, параметры игнорируются).

def getAnswer[T](i:AnyRef)(implicit m:ClassManifest[T]) = {
  val result = getResult(i)
  if (result.getClass == m.erasure) Some(result.asInstanceOf[T]) else None
}

> getAnswer[java.lang.Integer](2.asInstanceOf[AnyRef])
res4: Option[java.lang.Integer] = Some(2)

getAnswer[String](2.asInstanceOf[AnyRef])
res1: Option[String] = None
...