简体   繁体   中英

Getting proper type constructor parameters for a “refined” type

I'm having problems comparing the 'compatibility' between two types using reflection (actually I'm writing a macro). For example, I want to permit Vector[Int] === List[Int] . Now I know the general approach . But the problem is I cannot get the type constructor parameters in this case:

import scala.reflect._
import runtime.universe._

typeOf[List[Int]].typeArgs                             // List(Int) OK
typeOf[List[Int] with java.io.Serializable].typeArgs   // List()    FAIL

Why is this a problem?

def test[A, B >: A](a: A, b: B)(implicit tt: TypeTag[B]) = {
  println(s"tt = $tt")
  typeOf[B].typeArgs
}

Now this works:

test(List(1, 2, 3), List(1, 2, 3))  // List(Int)

But this doesn't:

test(Vector(1, 2, 3), List(1, 2, 3))  // List()

One can use an extractor called RefinedType :

def test[A, B >: A](a: A, b: B)(implicit tt: TypeTag[B]): List[List[Type]] = {
  val all = typeOf[B] match {
    case RefinedType(parents, scope) => parents.map(_.typeArgs)
    case x => x.typeArgs :: Nil
  }
  all.filter(_.nonEmpty)
}

test(List(1, 2, 3), List(1, 2, 3))
test(Vector(1, 2, 3), List(1, 2, 3))

Then one still has to somehow find a strategy to align the parents. (I'm testing all combinations now).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM