无形的=:!=
(以及类似类型的不等式运算符)本质上利用不明确的隐式将 Prolog 式的否定编码为失败。而且,正如您所观察到的,Scala 没有一种机制允许库作者在出现歧义时提供更有意义的错误消息。也许它应该,或者也许 Scala 应该提供一种更直接的类型否定表示,使得这种编码变得不必要。
鉴于您已经提出了这个问题Nats
我认为您尝试处理类型不平等可能是合理的。如果不是的话Nats
我的推荐回答另一个问题 https://stackoverflow.com/questions/24926521/is-ambiguous-implicit-value-the-only-way-we-want-to-make-the-error-existed-in-co直接编码感兴趣的关系的类型类也适用于此。但事实上,我建议使用相同的解决方案作为解决方法,以解决无法提供更好的错误消息的问题。
import shapeless._, nat._, ops.nat._
@annotation.implicitNotFound(msg = "${A} + ${B} = ${N}")
trait SumNotN[A <: Nat, B <: Nat, N <: Nat]
object SumNotN {
implicit def sumNotN[A <: Nat, B <: Nat, R <: Nat, N <: Nat]
(implicit sum: Sum.Aux[A, B, R], error: R =:!= N): SumNotN[A, B, N] =
new SumNotN[A, B, N] {}
}
def typeSafeSum[T <: Nat, W <: Nat](x: T, y: W)
(implicit valid: SumNotN[T, W, _7]) = x
scala> typeSafeSum(_3, _4)
<console>:20: error: shapeless.nat._3 + shapeless.nat._4 = shapeless.nat._7
typeSafeSum(_3, _4)
^
该技术(将预期的模糊隐式隐藏在我们期望在潜在歧义的情况下找不到的隐式后面)通常适用,但显然相当重量级......这是如果可能的话应避免类型不等式的另一个原因。