【问题标题】:Conditionally generating implicits in scala在scala中有条件地生成隐式
【发布时间】:2018-05-05 10:50:09
【问题描述】:

我正在研究一个链接隐式函数的系统,它类似于下面的简化示例。测试c1.payload == c2.payload 代表我需要做的不在“类型空间”中的测试;我曾期望我会放入一个宏来定义witnessEvidence,但是 Scala 显然不允许使用任意类型的隐式参数(仅限 WeakTypeTag 值!)的宏定义,所以我对如何继续感到有些困惑有了这个。下面的代码在逻辑上显示了我想要发生的事情,但是隐式函数不能有条件地产生或不产生证据(除非它在宏实现中)。

case class Capsule[T](payload: Int)

trait A
trait B
trait C

implicit val capa = Capsule[A](3)
implicit val capb = Capsule[B](3)
implicit val capc = Capsule[C](7)

case class Evidence[T1, T2](e: Int)

implicit def witnessEvidence[T1, T2](implicit c1: Capsule[T1], c2: Capsule[T2]): Evidence[T1, T2] = {
  if (c1.payload == c2.payload)
    Evidence[T1, T2](c1.payload)
  else
    // Do not produce the evidence
}

def foo[T1, T2](implicit ev: Evidence[T1, T2]) = ev.e

val f1 = foo[A, B] // this should compile
val f2 = foo[A, C] // this should fail with missing implicit!

【问题讨论】:

  • 在编译时是否知道Capsule 值,尤其是它们的payload 字段?
  • payload 值是作为链式隐式解析的副产品生成的(这部分似乎工作正常)。所以它在编译时可用。但是信息不是以类型的形式编码的。我正在研究一种替代方法,将信息编码为 HList 记录,以便隐式解析可以代替它。

标签: scala macros scala-macros implicits


【解决方案1】:

这是不可能的,因为隐式解析是在编译时完成的,而对值等价的测试是在运行时完成的。

要实现这一点,您需要让编译器将值理解为类型,以便您可以要求两个 3 的类型相等并使用它来推断 capa =:= capb。为此,您可以使用单例类型:https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#singleton-typed-literals

如果您需要在普通相等比较之外进行算术运算,则需要使用Nat:https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/nat.scala

【讨论】:

猜你喜欢
  • 2014-06-13
  • 2015-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 2021-02-17
  • 1970-01-01
  • 2018-06-22
相关资源
最近更新 更多