Search code examples
scalatypescompiler-errorstype-systems

Polymorphic return type by using TypeTag in Scala


What I want to do is returning generics type in Scala function by using TypeTag. Here is the example code.

trait Parent[T]

object IntChild extends Parent[Int]
object StringChild extends Parent[String]

object SomeClass {
  def of[A: TypeTag]: Parent[T] = {
    getElementType[A] match {
      case Int => IntChild
      case String => StringChild
    }
  }
}

SomeClass.of[Array[Int]]

But it throws a compile error. Because the returned type of of method is not fixed in the compile type. Is there any way to get the type information from TypeTag and embed the type in the returned type?

What I am expecting is like

// T is inferred from TypeTag A.
def of[A: TypeTag, T]: Parent[T] = {
  //...
}

I found this code also has not passed compile. So we need to fix the type information inferred from A's TypeTag.

def of[A: TypeTag]: Parent[_] = {
  //...
}

This is the error.

type mismatch;
[error]  found   : Array[Int]
[error]  required: Array[_$1]

How can I get the element type in advance?


Solution

  • I'm not sure it's possible with those definitions. How about changing the definitions a little?

    trait Parent[T]
    
    implicit object IntChild extends Parent[Int]
    implicit object StringChild extends Parent[String]
    
    object SomeClass {
      def of[A: Parent]: Parent[A] = implicitly
    }
    

    This makes sure everything is done at the type level so that you get the return type you want. It requires the implicit modifier on IntChild and StringChild. There's no need to have another type parameter named T, as it would always be the same as A in your example.