Scala проверяет тип дженериков

Как мне сделать что-то подобное в Scala?

case class Foo[A](x: A) {

  def get[T]: Option[T] = x match {
    case x: T => Some(x)    // if x is of type T i.e. T =:= A
    case _ => None
  }
}

val test = Foo("hi")
assert(test.get[Int] == None)
assert(test.get[String] == Some("hi"))

Я попробовал это и столкнулся с какой-то странной ошибкой вывода времени:

import scala.util.{Try, Success}
import reflect._

case class Foo[A](x: A) extends Dynamic {

  def get[T: ClassTag]: Option[T] = Try(x.asInstanceOf[T]) match {
    case Success(r) => Some(r) 
    case _ => None
  }
}

object Foo extends App {
  val test = Foo("hi")
  val wtf: Option[Int] = test.get[Int]
  assert(wtf.isInstanceOf[Option[String]])
  assert(wtf == Some("hi"))     // how????
  // val wtf2: Option[String] = wtf  // does not compile even if above assert passes!!
}

person pathikrit    schedule 12.03.2014    source источник
comment
Посмотрите на предупреждение при компиляции с флагом -unchecked: scala> case class Foo[A](x: A) { | | def get[T]: Option[T] = x match { | case x: T => Some(x) // if x is of type T i.e. T =:= A | case _ => None | } | } <console>:10: warning: abstract type T in type pattern T is unchecked since it is eliminated by erasure case x: T => Some(x) // if x is of type T i.e. T =:= A. Затем см. stackoverflow.com/a/3789230/2197460. Не ответ, а начало.   -  person Dave Swartz    schedule 12.03.2014
comment
В ссылке, которую вы разместили, автор спрашивает об общем случае T в конце вопроса.   -  person pathikrit    schedule 12.03.2014
comment
с/время/тип. Или с/работа/сон.   -  person som-snytt    schedule 12.03.2014


Ответы (2)


Наверняка дурак, но поспешно:

scala> :pa
// Entering paste mode (ctrl-D to finish)

import reflect._
case class Foo[A](x: A) {

  def get[T: ClassTag]: Option[T] = x match {
    case x: T => Some(x)    // if x is of type T i.e. T =:= A
    case _ => None
  }
}

// Exiting paste mode, now interpreting.

import reflect._
defined class Foo

scala> val test = Foo("hi")
test: Foo[String] = Foo(hi)

scala> test.get[Int]
res0: Option[Int] = None

scala> test.get[String]
res1: Option[String] = Some(hi)
person som-snytt    schedule 12.03.2014

Если вы можете выбросить get:

case class Foo[A](x: A)
Seq(Foo("hi"), Foo(1), Foo(2d)).collect { case f @ Foo(x: String) => f }.foreach(println)

приводит к:

Foo(hi)

И остальные такие же тривиальные.

person Dave Swartz    schedule 12.03.2014
comment
get был просто упрощением для StackOverflow — мне нужен метод с общим типом T. - person pathikrit; 12.03.2014