如何在Scala中反映与抽象类型的类型参数相对应的具体类型?

Erp12

假设我们有一个通用类型(例如Seq[E])和一个具体子类型(例如Seq[Int])。我们如何提取与抽象类型的类型参数相对应的具体类型。换句话说,我们怎么知道E -> Int

下面是测试所需行为的最小代码示例。extractTypeBinding函数将执行相关转换。

import scala.reflect.runtime.{universe => ru}

class MyFuncs

object MyFuncs {
  def fn1[E](s: Seq[E]): E = ???
  def fn2[K, V](m: Map[K, V]): Int = ???
}

object Scratch {

  def extractTypeBinding(genType: ru.Type, typeParam: ru.Type)(concreteType: ru.Type): ru.Type = ???

  def getArgTypes(methodSymbol: ru.MethodSymbol): Seq[ru.Type] =
    methodSymbol.paramLists.headOption.getOrElse(Nil).map(_.typeSignature)

  def main(a: Array[String]): Unit = {

    // Grab the argument types of our methods.
    val funcsType = ru.typeOf[MyFuncs].companion
    val fn1ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn1")).asMethod)
    val fn2ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn2")).asMethod)

    val genericSeq = fn1ArgTypes.head  // Seq[E]
    val genericMap = fn2ArgTypes.head  // Map[K, V]

    // Create an extractor for the `E` in `Seq[E]`.
    val seqElExtractor = extractTypeBinding(genericSeq, genericSeq.typeArgs.head) _
    // Extractor for the `K` in `Map[K,V]`
    val mapKeyExtractor = extractTypeBinding(genericMap, genericMap.typeArgs.head) _
    // Extractor for the `V` in `Map[K,V]`
    val mapValueExtractor = extractTypeBinding(genericMap, genericMap.typeArgs(1)) _

    println(seqElExtractor(ru.typeOf[Seq[Int]])) // should be Int
    println(seqElExtractor(ru.typeOf[Seq[Map[String, Double]]])) // should be Map[String, Double]
    println(mapKeyExtractor(ru.typeOf[Map[String, Double]])) // should be String
    println(mapKeyExtractor(ru.typeOf[Map[Int, Boolean]])) // should be Int
    println(mapValueExtractor(ru.typeOf[Map[String, Double]])) // should be Double
    println(mapValueExtractor(ru.typeOf[Map[Int, Boolean]])) // should be Boolean
  }

}

基于文档字符串,似乎asSeenFrom应该是实现的关键extractTypeBinding我尝试了以下实现,但返回的类型参数保持不变。

  def extractTypeBinding(genType: ru.Type, typeParam: ru.Type)(concreteType: ru.Type): ru.Type =
    typeParam.asSeenFrom(concreteType, genType.typeSymbol.asClass)
  
  ...

  println(seqElExtractor(ru.typeOf[Seq[Int]])) // E
  println(seqElExtractor(ru.typeOf[Seq[Map[String, Double]]])) // E

如果asSeenFrom是正确的方法,正确的咒语是什么?如果没有,那该怎么办呢?

Erp12

最简单的解决方案来自Dmytro Mitin的评论。

我对此进行了一些误解.typeArgs,并通过其他一些实验得以解决。

  1. 它返回所有类型参数,而不仅仅是抽象参数。
  2. 它仅返回调用类型的“顶级”类型参数。换句话说,Map[A, Map[B, C]]只有2个类型的args(AMap[B, C]

这两个现在看起来都非常直观,但是我最初做了一些愚蠢的假设。以下是我测试的修改版本,可以更清楚地实现我的初衷。

class MyFuncs

object MyFuncs {
  def fn1[E](s: Seq[E]): E = ???
  def fn2[K, V](m: Map[K, V]): Int = ???
}

object Scratch {

  def typeArgBindings(genericType: ru.Type, concreteType: ru.Type): Map[ru.Type, ru.Type] =
    // @todo consider validating both have the same base type.
    genericType.typeArgs.zip(concreteType.typeArgs).toMap

  def getArgTypes(methodSymbol: ru.MethodSymbol): Seq[ru.Type] =
    methodSymbol.paramLists.headOption.getOrElse(Nil).map(_.typeSignature)

  def main(a: Array[String]): Unit = {

    // Grab the argument types of our methods.
    val funcsType = ru.typeOf[MyFuncs].companion
    val fn1ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn1")).asMethod)
    val fn2ArgTypes = getArgTypes(funcsType.member(ru.TermName("fn2")).asMethod)

    val genericSeq = fn1ArgTypes.head  // Seq[E]
    val genericMap = fn2ArgTypes.head  // Map[K, V]

    println(typeArgBindings(genericSeq, ru.typeOf[Seq[Int]]))  // Map(E -> Int)
    println(typeArgBindings(genericSeq, ru.typeOf[Seq[Map[String, Double]]]))  // Map(E -> Map[String,Double])
    println(typeArgBindings(genericMap, ru.typeOf[Map[String, Double]]))  // Map(K -> String, V -> Double)
    println(typeArgBindings(genericMap, ru.typeOf[Map[Int, Boolean]]))  // Map(K -> Int, V -> Boolean)

  }

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在具有抽象类型变量的基本特征中反映Scalavro联合类型?

来自分类Dev

返回抽象类中的具体类型

来自分类Dev

Scala:使用类型参数或抽象类型作为类型界限

来自分类Dev

如何在F#中创建类型参数抽象类型?

来自分类Dev

如何在 Julia 中为抽象类型的所有参数子类型定义方法?

来自分类Dev

如何具体设置类型绑定的抽象类型?

来自分类Dev

如何在Julia中将抽象类型的子类型指定为类型参数?

来自分类Dev

如何指示抽象成员将返回 Scala 中的具体类型

来自分类Dev

如何在AGDA中定义抽象类型

来自分类Dev

如何在AGDA中定义抽象类型

来自分类Dev

Scala抽象类型成员

来自分类Dev

Scala 中的抽象类型、变量和类型类

来自分类Dev

参数局部抽象类型

来自分类Dev

抽象类的具体子类的Typescript类型

来自分类Dev

引用类型参数的抽象类型成员

来自分类Dev

在scala中,如何使抽象类型的内部类型对不同实例保持不变?

来自分类Dev

Scala-抽象类型和隐式参数解析

来自分类Dev

Scala Akka:使用子类型参数实现抽象类

来自分类Dev

如何返回抽象类型?

来自分类Dev

R中的抽象类型

来自分类Dev

如何对抽象类型使用类型约束

来自分类Dev

我如何在抽象类中声明任何类型的数组(从给定类型派生)?

来自分类Dev

如何在 Julia Base 中查找抽象类型的子类型?

来自分类Dev

REST 如何实现多态 POST 端点:抽象类型需要映射到具体类型

来自分类Dev

与其他语言相比,Java中的具体类型和抽象类型

来自分类Dev

与其他语言相比,Java中的具体类型和抽象类型

来自分类Dev

Scala中通用抽象类型的模式匹配

来自分类Dev

Scala中具有抽象类型的F界多态

来自分类Dev

抽象类类型签名中的可选参数

Related 相关文章

  1. 1

    如何在具有抽象类型变量的基本特征中反映Scalavro联合类型?

  2. 2

    返回抽象类中的具体类型

  3. 3

    Scala:使用类型参数或抽象类型作为类型界限

  4. 4

    如何在F#中创建类型参数抽象类型?

  5. 5

    如何在 Julia 中为抽象类型的所有参数子类型定义方法?

  6. 6

    如何具体设置类型绑定的抽象类型?

  7. 7

    如何在Julia中将抽象类型的子类型指定为类型参数?

  8. 8

    如何指示抽象成员将返回 Scala 中的具体类型

  9. 9

    如何在AGDA中定义抽象类型

  10. 10

    如何在AGDA中定义抽象类型

  11. 11

    Scala抽象类型成员

  12. 12

    Scala 中的抽象类型、变量和类型类

  13. 13

    参数局部抽象类型

  14. 14

    抽象类的具体子类的Typescript类型

  15. 15

    引用类型参数的抽象类型成员

  16. 16

    在scala中,如何使抽象类型的内部类型对不同实例保持不变?

  17. 17

    Scala-抽象类型和隐式参数解析

  18. 18

    Scala Akka:使用子类型参数实现抽象类

  19. 19

    如何返回抽象类型?

  20. 20

    R中的抽象类型

  21. 21

    如何对抽象类型使用类型约束

  22. 22

    我如何在抽象类中声明任何类型的数组(从给定类型派生)?

  23. 23

    如何在 Julia Base 中查找抽象类型的子类型?

  24. 24

    REST 如何实现多态 POST 端点:抽象类型需要映射到具体类型

  25. 25

    与其他语言相比,Java中的具体类型和抽象类型

  26. 26

    与其他语言相比,Java中的具体类型和抽象类型

  27. 27

    Scala中通用抽象类型的模式匹配

  28. 28

    Scala中具有抽象类型的F界多态

  29. 29

    抽象类类型签名中的可选参数

热门标签

归档