使用“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”查找可用的类型类实例的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Selenium 和 Python 查找从 covid 中恢复的人数的类路径
C# 使用‘反射(Assembly)’查找具有指定‘特性(Attributes) ’的类