我正在研究一个链式隐式函数系统,它类似于下面的简化示例。测试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!
答案 0 :(得分:4)
这是不可能的,因为隐式解析是在编译时完成的,而值等价的测试是在运行时完成的。
为了使这项工作,您需要使编译器将值理解为类型,以便您可以要求两个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