Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 了解类型构造函数扩展的类型构造函数的类型参数,找出类型构造函数的类型参数_Scala_Scala Reflect - Fatal编程技术网

Scala 了解类型构造函数扩展的类型构造函数的类型参数,找出类型构造函数的类型参数

Scala 了解类型构造函数扩展的类型构造函数的类型参数,找出类型构造函数的类型参数,scala,scala-reflect,Scala,Scala Reflect,设X为类型构造函数,类型参数为A1,A2,…,An。例如选项[A]和功能1[A1、A2] 设X[T1,T2,…,Tn]为将类型构造函数X应用于具体类型参数T1,T2Tn。例如Option[Int]和Function1[Long,List[String]] 假设Y是X的一个直接子类,它保留X的一些类型参数不固定,不添加新的自由类型参数,其类型参数是B1,B2,…,Bm和m,这是部分答案。它只找出基类X的类型参数与直接子类Y的类型参数之间的关系 import scala.reflect.runtim

X
为类型构造函数,类型参数为
A1
A2
,…,
An
。例如
选项[A]
功能1[A1、A2]

X[T1,T2,…,Tn]
为将类型构造函数
X
应用于具体类型参数
T1
T2
<代码>Tn。例如
Option[Int]
Function1[Long,List[String]]


假设
Y
X
的一个直接子类,它保留
X
的一些类型参数不固定,不添加新的自由类型参数,其类型参数是
B1
B2
,…,
Bm
m,这是部分答案。它只找出基类
X
的类型参数与直接子类
Y
的类型参数之间的关系

import scala.reflect.runtime.universe._

/** @param baseType a type resulting of the instantiation of a type constructor. For example: {{{typeOf[Option[Int]]}}}
 * @param directSubclassTypeConstructor the type constructor whose type parameters we want to instantiate. It should be a subclass of the `baseType`'s type constructor.
 * @return the relationship between `baseType`'s type arguments and `directSubclassTypeconstructor`'s type parameters. For example: {{{Map(A -> Int)}}}*/
def typeParametersToBaseTypeArgumentsRelationship(baseType: Type, directSubclassTypeConstructor: Type): Map[Type, Type] = {
    val baseTypeConstructor = baseType.typeConstructor;
    assert(directSubclassTypeConstructor <:< baseTypeConstructor)

    val typeParamsRelationship =
        for {
            (baseTypeParam, baseTypeArgument) <- baseTypeConstructor.typeParams zip baseType.typeArgs
        } yield {
            val directSubclassTypeParam = baseTypeParam.asType.toType.asSeenFrom(directSubclassTypeConstructor, baseType.typeSymbol)
            directSubclassTypeParam -> baseTypeArgument
        }
    typeParamsRelationship.toMap
}
另一个更有趣的用法示例:

scala> import scala.reflect.runtime.universe._
scala> typeParametersToBaseTypeArgumentsRelationship(
    typeOf[Function1[Long, List[String]]],
    typeOf[PartialFunction[_, _]].typeConstructor
)
val res1: Map[reflect.runtime.universe.Type, reflect.runtime.universe.Type] =
    Map(A -> Long, B -> List[String])
sealed trait X[A1, A2, A3]
class Y[B1, B2] extends X[B2, List[B1], B1] {}

scala> typeParametersToBaseTypeArgumentsRelationship(
    typeOf[X[Long, List[String], String]],
    typeOf[Y[_, _]].typeConstructor
)
val res2: Map[reflect.runtime.universe.Type,reflect.runtime.universe.Type] =
    Map(B2 -> Long, List[B1] -> List[String], B1 -> String)
scala> applySubclassTypeConstructor(
    typeOf[Option[Int]],
    typeOf[Some[_]].typeConstructor
)
val res1: reflect.runtime.universe.Type =
     Some[Int]
sealed trait X[A1, A2, A3]
class Y[B1, B2] extends X[B2, List[B1], B1] {}

scala> applySubclassTypeConstructor(
    typeOf[X[Long, List[String], String]],
    typeOf[Y[_, _]].typeConstructor
)
val res2: reflect.runtime.universe.Type =
    Y[String,Long]
回答这个问题缺少的部分是创建一个带有根据给定关系实例化的类型参数的
directSubclassTypeConstructor
副本。这需要我所没有的知识

编辑: 在了解了如何将类型参数应用于类型构造函数之后,我能够完成这个答案

import scala.reflect.runtime.universe._

/** Given a type `baseType` and a type constructor of one of its direct subclasses `directSubclassTypeConstructor`, creates a type by applying said type constructor to the type arguments that were used to create the `baseType` as seen from said direct subclass.
 * @param baseType a type resulting of the instantiation of a type constructor. For example: {{{typeOf[Option[Int]]}}}
 * @param directSubclassTypeConstructor the type constructor we want to instantiate such that it is assignable to `baseType`. For example: {{{typeOf[Some[_]].typeConstructor}}}
 * @return the type constructed by applying the type constructor `directSubclassTypeConstructor` to the type arguments of `baseType` as seen from said type constructor. For example: {{{typeOf[Some[Int]]}}}*/
def applySubclassTypeConstructor(baseType: Type, directSubclassTypeConstructor: Type): Type = {
    val directSubclassTypeParams = directSubclassTypeConstructor.typeParams
    if( directSubclassTypeParams.isEmpty) {
        directSubclassTypeConstructor
    } else {
        val baseTypeConstructor = baseType.typeConstructor;
        assert(directSubclassTypeConstructor <:< baseTypeConstructor)

        val subclassTypeParamsToBaseTypeArgumentsRelationship=
            for {
                (baseTypeParam, baseTypeArgument) <- baseTypeConstructor.typeParams zip baseType.typeArgs
            } yield {
                val directSubclassTypeParam = baseTypeParam.asType.toType.asSeenFrom(directSubclassTypeConstructor, baseType.typeSymbol)
                directSubclassTypeParam -> baseTypeArgument
            }

        val directSubclassTypeArguments =
            for (subclassTypeParm <- directSubclassTypeParams) yield {
                subclassTypeParamsToBaseTypeArgumentsRelationship.find { r =>
                    r._1.typeSymbol.name == subclassTypeParm.name
                }.get._2
            }

        appliedType(directSubclassTypeConstructor, directSubclassTypeArguments)
    }
}
intrincate使用示例:

scala> import scala.reflect.runtime.universe._
scala> typeParametersToBaseTypeArgumentsRelationship(
    typeOf[Function1[Long, List[String]]],
    typeOf[PartialFunction[_, _]].typeConstructor
)
val res1: Map[reflect.runtime.universe.Type, reflect.runtime.universe.Type] =
    Map(A -> Long, B -> List[String])
sealed trait X[A1, A2, A3]
class Y[B1, B2] extends X[B2, List[B1], B1] {}

scala> typeParametersToBaseTypeArgumentsRelationship(
    typeOf[X[Long, List[String], String]],
    typeOf[Y[_, _]].typeConstructor
)
val res2: Map[reflect.runtime.universe.Type,reflect.runtime.universe.Type] =
    Map(B2 -> Long, List[B1] -> List[String], B1 -> String)
scala> applySubclassTypeConstructor(
    typeOf[Option[Int]],
    typeOf[Some[_]].typeConstructor
)
val res1: reflect.runtime.universe.Type =
     Some[Int]
sealed trait X[A1, A2, A3]
class Y[B1, B2] extends X[B2, List[B1], B1] {}

scala> applySubclassTypeConstructor(
    typeOf[X[Long, List[String], String]],
    typeOf[Y[_, _]].typeConstructor
)
val res2: reflect.runtime.universe.Type =
    Y[String,Long]

很明显,对于某些[R1]@SimY4,R1=T1我所说的是正确的,因为我澄清了“去掉了差异”。它认为这是可以解决的。如果我是对的,编译器需要为类型推断解决它,还有“@SimY4请查看方法
def asSeenFrom(pre:type,clazz:Symbol)的文档:Type
定义于
scala.reflect.api.Types
。显然它解决了这个问题。但我不知道如何使用它。文档中的示例已过时,因为它使用了从api中删除的
ThisType
。旁注:我确信有更好的方法来表达“可分配且已删除差异”“,因为我缺少术语。如果我将其替换为“对应于”。@Readren使用
internal.thisType(C)
而不是
thisType(C)
,问题可能会更清楚。