使用“Prolog in Scala”查找可用的类型类实例

Posted

技术标签:

【中文标题】使用“Prolog in Scala”查找可用的类型类实例【英文标题】:Using the "Prolog in Scala" to find available type class instances 【发布时间】:2014-12-30 15:30:27 【问题描述】:

考虑到https://speakerdeck.com/folone/theres-a-prolog-in-your-scala,我想“滥用”Scala 类型系统来查找所有实例,例如CanBuildFrom 匹配给定条件。 Prolog 风格,我会在以下伪代码行中评估一些内容:

can_build_from(Src, int, list[int])
Src = somecollectiontype1[int]
Src = somecollectiontype2[int]
... etc

即运行时将查找满足语句 can_build_from(Src, int, list[int])Src 的所有值。

现在,我知道 Scala 隐式查找系统所在的原始约束/逻辑编程环境并不打算用于此类技巧,并且不能“返回”多个找到的值Src 开箱即用,所以我的问题是:是否有一个“魔术”让它工作,以便我以某种方式在 CanBuildFrom[X, Int, List[Int]] 中获得 X 的所有可能值?

其他示例:

trait CanFoo[T, U]

implicit val canFooIntString  = new CanFoo[Int,     String] 
implicit val canFooDblString  = new CanFoo[Double,  String] 
implicit val canFooBoolString = new CanFoo[Boolean, String] 
implicit val canFooIntSym     = new CanFoo[Int,     Symbol] 
implicit val canFooDblSym     = new CanFoo[Double,  Symbol] 
implicit val canFooBoolSym    = new CanFoo[Boolean, Symbol] 

现在我想查询CanFoo[X, String] 并返回X ∈ [Int, Double, Boolean],或者CanFoo[Int, X] 并返回X ∈ [String, Symbol]

或者,CanFoo[X, String] 将返回 List(canFooIntString, canFooDblString, canFooBoolString),即所有匹配的 CanFoo 实例。

【问题讨论】:

在这种情况下,集合是无限的:X 可以是 List[T] 对于所有 T ...我怀疑这不是你所追求的。 @MilesSabin:即使使用List[Int] 作为输出集合?也许我那时不理解 CanBuildFrom,但这个想法可以普遍适用吗? 我不清楚大致的想法实际上是什么......你能再举几个例子吗? @MilesSabin:我添加了一个更简单的示例。 @EECOLOR:实际上我是在试图找出哪些实例可用于CanBuildFrom 类型类。 【参考方案1】:

这可以通过编译器内部实现(至少在某些情况下)

import scala.language.experimental.macros
import scala.reflect.internal.util
import scala.reflect.macros.blackbox, contexts

object Macros 

  def allImplicits[A]: List[String] = macro impl[A]

  def impl[A: c.WeakTypeTag](c: blackbox.Context): c.Tree = 
    import c.universe._

    val context = c.asInstanceOf[contexts.Context]
    val global: context.universe.type = context.universe
    val analyzer: global.analyzer.type = global.analyzer
    val callsiteContext = context.callsiteTyper.context

    val tpA = weakTypeOf[A]

    val search = new analyzer.ImplicitSearch(
      tree = EmptyTree.asInstanceOf[global.Tree],
      pt = tpA.asInstanceOf[global.Type],
      isView = false,
      context0 = callsiteContext.makeImplicit(reportAmbiguousErrors = false),
      pos0 = c.enclosingPosition.asInstanceOf[util.Position]
    )

    q"$search.allImplicits.map(_.tree.symbol.toString).distinct"
  


allImplicits[CanFoo[_, String]]
// List(value canFooBoolString, value canFooDblString, value canFooIntString)

在 2.13.0 中测试。

【讨论】:

以上是关于使用“Prolog in Scala”查找可用的类型类实例的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AirPlay 查找可用屏幕?

在父元素中查找可见的类元素[重复]

如何使用 Selenium 和 Python 查找从 covid 中恢复的人数的类路径

C# 使用‘反射(Assembly)’查找具有指定‘特性(Attributes) ’的类

查找运行测试的类时出错,即使我在 IDE 中使用了自动测试创建功能

使用 Postgres 范围的递归 SQL 查询以查找可用性