Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we match Any to a generic type? [Scala 2.8]

Please point me to correct link if this has been answered before.

I have this code:

def getResult(a:Any):Any = a

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

This gives me a unchecked warning and everything matches to T. For instance, when I do getAnswer[Int](2), I get Some(2) (as expected). However, if I do getAnswer[String](2), I also get Some(2) which is not expected (I need None).

Is there any way to work around type erasure and somehow get getAnswer to work correctly (i.e., return Some(result) if and only if the result is of type T)?

Thanks in advance.

like image 373
Jus12 Avatar asked Feb 01 '11 06:02

Jus12


People also ask

Can generic class handle any type of data?

A generic class and a generic method can handle any type of data.

What is generic type in Scala?

Generic classes are classes which take a type as a parameter. They are particularly useful for collection classes.

Does Scala support generics?

The classes that takes a type just like a parameter are known to be Generic Classes in Scala. This classes takes a type like a parameter inside the square brackets i.e, [ ].


2 Answers

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
}

As Alexey wrote, you have some trouble with primitives. The technique used in the Scala sources in such cases involves always separate matches for every single primitive type, so I guess there is no way around.

like image 192
Landei Avatar answered Sep 21 '22 12:09

Landei


This works with some limitations (T must be a class and not a primitive type; if T is generic, parameters are ignored).

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
like image 42
Alexey Romanov Avatar answered Sep 22 '22 12:09

Alexey Romanov