有条件地产生scala中的含义

时间:2017-11-21 20:30:23

标签: scala macros scala-macros implicits

我正在研究一个链式隐式函数系统,它类似于下面的简化示例。测试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!

1 个答案:

答案 0 :(得分:4)

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

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

如果您需要在纯粹的平等比较之外进行算术运算,则需要使用Nathttps://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/nat.scala