Search code examples
genericsdefaultscala-option

Scala default TypeTag


I'm using typetags in Scala to match options

def foo[T: TypeTag](bar: Any) = {
  bar match {
    case option: Option[T] => option match {
      case x if typeOf[T] <:< typeOf[List[Any]] => println("List Option")
      case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
      case x if typeOf[T] <:< typeOf[Boolean] => println("Boolean Option")
      case _ => println("String")
    }
    case _ => println("no Option")
  }
}

So when I use the function this way

foo[List[Any]](val)

all will be fine and the output is "List Option" in this case. But when I try to use it without the TypeTag

foo(val)

the outputs is "List Option", regardless of whether it's a Option[List[Any]] or Option[String].

So now my question: Is it possible to define a default value for my TypeTag T? I want to use my function without the TypeTag if it is not needed and then the output should be "String" and not "List Option". It is possible to define a default value for parameters, so maybe it is for TypeTag too.


Solution

  • Your problem is that the type T is not related to the type of the parameter bar.

    This means, if you don't add the the type explicitly, the compiler will infer Nothing because it has no further information.

    Nothing is a subtype of everything, so your subtype checks succeeds in the first branch already (in fact all your cases are true for Nothing).

    Your code could be "improved" like this:

    import scala.reflect.runtime.universe._
    def foo[T: TypeTag](bar: Any) = {
      bar match {
        case option: Option[T] => option match {
          case x if typeOf[T] =:= typeOf[Nothing]       => println("Nothing")
          case x if typeOf[T] <:< typeOf[List[Any]]     => println("List Option")
          case x if typeOf[T] <:< typeOf[Map[Any, Any]] => println("Map Option")
          case x if typeOf[T] <:< typeOf[Boolean]       => println("Boolean Option")
          case _ => println("String")
        }
        case _ => println("no Option")
      }
    }
    

    I say "improved" because one should never ever write code like this. It feels like it tries to shoehorn some idiom from untyped languages into Scala.