当前位置: 首页 > 知识库问答 >
问题:

在Scala中,是否可以从更一般的类型中获得某物的单例类型?

马祺
2023-03-14
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.
}
def getSingletonType[T <: SS](string: String): T = ???

那也许我可以

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

还是这是不可能的?也许只有在编译时了解了所有的信息,您才能做这种事情?

共有1个答案

夏华藏
2023-03-14

通常,蕴涵是在编译时解析的。但是val string=stdin.readline()只有在运行时才知道。基本上,您可以将隐式解析推迟到运行时,但您只能在运行时应用这种解析的结果,而不能在编译时应用(静态类型等)

object Entry {
  implicit val e1 = ...
  implicit val e2 = ...
}

import scala.reflect.runtime.universe._
import scala.reflect.runtime
import scala.tools.reflect.ToolBox
val toolbox = ToolBox(runtime.currentMirror).mkToolBox()

def resolve(s: String): Any = {
  val typ = appliedType(
    typeOf[Entry[_]].typeConstructor,
    internal.constantType(Constant(s))
  )
  val instanceTree = toolbox.inferImplicitValue(typ, silent = false)
  val instance = toolbox.eval(toolbox.untypecheck(instanceTree)).asInstanceOf[Entry[_]]
  instance.value
}

resolve("S") // 3

val string = StdIn.readLine()
resolve(string)
// 3 if you enter S
// ABC if you enter T
// "scala.tools.reflect.ToolBoxError: implicit search has failed" otherwise

请注意,我将implicits放入type class的陪伴对象中,以便使它们在隐式范围内可用,因此在工具箱范围内可用。否则,代码应稍作修改:

object EntryImplicits {
  implicit val e1 = ...
  implicit val e2 = ...
}

// val instanceTree = toolbox.inferImplicitValue(typ, silent = false)
//   should be replaced with
val instanceTree =
  q"""
    import path.to.EntryImplicits._
    implicitly[$typ]
  """

在您的代码中,importpath.to.entryimplicits._importmain._

 类似资料:
  • 问题内容: 是否可以将类中某个类的实例设置为null。例如,我可以做这样的事情吗 我已经尝试过了,但是行不通。使用“ this = null”,我得到一个错误,即左侧必须是一个变量。有没有办法实现类似的目标? 问题答案: 一个对象的实例不知道哪些引用可能在引用它,因此该对象中的代码无法使这些引用无效。您要的是不可能的(*)。 至少没有添加一堆脚手架来跟踪所有参考,并且以某种方式通知其所有者应该将它

  • 我想在编译时使用类型的名称。例如,假设我写过: 现在我想拥有: 但是唉,只是,而不是常量表达式。。。是否有其他的constexpr方法来获取类型的名称?

  • 我想声明一个像belove这样的类 但是它似乎没有语法来支持这一点,它有任何方法可以保持在

  • 问题内容: 你好 我想获得在运行时在Java中实现接口的类的列表,这样我就可以进行查找服务而不必对其进行硬编码。有没有简单的方法可以做到这一点?我不害怕 问题答案: 最简洁的答案是不。 长的答案是,子类可以以多种方式出现,从根本上说,根本不可能分类找到它们。 您无法在运行时执行此操作,但只有在加载了类以及如何知道它们已加载后才能找到类?您可以扫描每个JAR和类文件,但这不是确定的。另外,还有URL

  • 问题内容: 是否可以实例化t1的reflect.Type? 是否可以通过将名称“ t1”作为字符串来获取t1的reflect.Type? 问题答案: 在1,是的,有点: 无需实例化。但是,Go没有类型文字,这是我想您要的。要获取类型的运行时值,您需要具有某种值。如果您不希望或无法在运行时创建该值,则可以从类型为nil的值中提取它。如果您不喜欢每次都查找的想法,可以将此运行时类型存储在变量中。 在2