首页 > 解决方案 > 无论如何,在 Scala 中,是否可以从更通用的类型中获取 Singleton 类型的东西?

问题描述

我有一种情况,我试图在单例类型上使用隐式解析。如果我在编译时知道单例类型,这将非常有效:

object Main {

    type SS = String with Singleton

    trait Entry[S <: SS] {
        type out
        val value: out
    }

    implicit val e1 = new Entry["S"] {
        type out = Int
        val value = 3
    }
    implicit val e2 = new Entry["T"] {
        type out = String
        val value = "ABC"
    }

    def resolve[X <: SS](s: X)(implicit x: Entry[X]): x.value.type = {
        x.value
    }

    def main(args: Array[String]): Unit = {
        resolve("S") //implicit found!  No problem
    }
}

但是,如果我在编译时不知道这种类型,那么我就会遇到问题。

def main(args: Array[String]): Unit = {
    val string = StdIn.readLine()
    resolve(string) //Can't find implicit because it doesn't know the singleton type at runtime.
}

无论如何我可以解决这个问题吗?也许某些方法采用 aString并返回该字符串的单例类型?

def getSingletonType[T <: SS](string: String): T = ???

那么也许我可以做

def main(args: Array[String]): Unit = {
    val string = StdIn.readLine()
    resolve(getSingletonType(string))
}

或者这是不可能的?如果您在编译时知道所有信息,也许您只能做这种事情?

标签: scalatypeclassimplicitsingleton-typescala-2.13

解决方案


如果您知道Entry编译时所有可能的实现(只有在密封时才有可能),那么您可以使用宏来创建映射/部分函数String -> Entry[_]

由于这对扩展是开放的,我担心充其量一些运行时反射将不得不扫描整个类路径以找到所有可能的实现。

但即便如此,您也必须以String某种方式将这个文字嵌入到每个实现中,因为 JVM 字节码对单例类型和实现之间的映射一无所知——只有 Scala 编译器知道。然后使用它来查找在所有实现中是否有一个(并且恰好一个)与您的值匹配 - 如果在同一范围内同时有两个实现,则在隐含的情况下编译将失败,但您可以拥有多个只要不一起出现在同一范围内,就可以实现。运行时反射将是全局的,因此无法避免冲突。

所以不,没有好的解决方案可以使这个编译时调度动态化。您可以自己创建这样的调度,例如自己编写Map[String, Entry[_]]并使用get函数来处理丢失的图片。


推荐阅读