gpt4 book ai didi

scala - 是否有一个类型类来检查是否存在至少一个隐式类型?

转载 作者:行者123 更新时间:2023-12-03 23:51:16 26 4
gpt4 key购买 nike

我有一个特质 Foo[T, U]以及给出 L <: HList 的类型级算法和目标类型 U , 告诉我是否存在 TL这样就有一个隐含的 Foo[T, U]在适用范围。这是使用以下类型类实现的:

trait Search[L <: HList, U]

object Search {
def apply[L <: HList, U](implicit s: Search[L, U]): U = null

...
}

我们有以下内容:
object Test {
type L = Int :: String :: HNil

implicit val foo: Foo[String, Boolean] = null

Search[L, Boolean] //compiles

Search[L, Double] //does not compile
}

如果没有 Foo[T, U],我希望搜索根本不会发生。对于任何 T在所有范围内,因为那时我们已经知道该算法将无法完成。换句话说,我想要一个类型类 trait Exists[F[_]]对于哪些实例存在当且仅当至少有一个隐式 F在范围内,所以函数 Search.apply而是有签名:
def apply[L <: HList, U](implicit ev: Exists[Foo[_, U]], s: Search[L, U]): U = null

在这种情况下,编译器只会尝试解析 s如果有任何隐含的 Foo在适用范围。

这样的类型类可以定义吗?一个已经存在了吗?

最佳答案

尝试

import scala.language.experimental.macros
import scala.reflect.macros.{blackbox, contexts}

trait Exists[A]

object Exists {
implicit def materialize[A]: Exists[A] = 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 searchResult = analyzer.inferImplicit(
tree = EmptyTree.asInstanceOf[global.Tree],
pt = tpA.asInstanceOf[global.Type],
reportAmbiguous = false,
isView = false,
context = callsiteContext,
saveAmbiguousDivergent = true,
pos = c.enclosingPosition.asInstanceOf[global.Position]
)

val isAmbiguous = callsiteContext.reporter.firstError match {
case Some(analyzer.AmbiguousImplicitTypeError(_,_)) => true
case _ => false
}

if (searchResult.isSuccess || searchResult.isAmbiguousFailure || isAmbiguous)
q"new Exists[$tpA] {}"
else c.abort(c.enclosingPosition, s"no implicit $tpA")
}
}

测试
// no implicit Int
// implicitly[Exists[Int]] // doesn't compile

implicit val i: Int = 1
implicitly[Exists[Int]] // compiles

implicit val i: Int = 1
implicit val i1: Int = 2
implicitly[Exists[Int]] // compiles

我猜原版 Search曾是
trait Foo[U, V]

trait Search[L <: HList, V]

trait LowPrioritySearch {
implicit def tail[H, T <: HList, V](implicit search: Search[T, V]): Search[H :: T, V] = null
}

object Search extends LowPrioritySearch {
def apply[L <: HList, U](implicit s: Search[L, U]): U = null.asInstanceOf[U]

implicit def head[U, T <: HList, V](implicit foo: Foo[U, V]): Search[U :: T, V] = null
}

现在与 Exists
def apply[L <: HList, U](implicit ev: Exists[Foo[_, U]], s: Search[L, U]): U = null.asInstanceOf[U]

也能用
Search[L, Boolean] //compiles
// Search[L, Double] //does not compile

在 2.13.0 中测试
libraryDependencies ++= Seq(
scalaOrganization.value % "scala-reflect" % scalaVersion.value,
scalaOrganization.value % "scala-compiler" % scalaVersion.value
)

关于scala - 是否有一个类型类来检查是否存在至少一个隐式类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57482298/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com