在使用无形类型不等式时,如何自定义Scala模糊隐式错误

时间:2014-07-29 00:25:21

标签: scala shapeless

def typeSafeSum[T <: Nat, W <: Nat, R <: Nat](x: T, y: W)
         (implicit sum: Sum.Aux[T, W, R], error: R =:!= _7) = x

typeSafeSum(_3, _4) //compilation error, ambiguous implicit found.

我不认为错误信息&#34;含糊不清的隐含发现&#34;是友好的,我怎么能自定义它来说像&#34; 2 NAT值的总和不应该等于7&#34;

非常感谢提前

1 个答案:

答案 0 :(得分:8)

无形的=:!=(以及类似的类型不等式运算符)固有地利用含糊不清的含义来将Prolog式否定编码为失败。而且,正如您所观察到的,Scala没有一种机制允许库作者在预期模糊时提供更有意义的错误消息。也许它应该,或者Scala应该提供更直接的表示否定类型的表示,使得这种编码变得不必要。

鉴于您已根据Nats提出问题,我认为您尝试使用类型不平等可能是合理的。如果answer to another question中我的建议不是Nats,那么直接编码感兴趣关系的类型类也适用于此。尽管如此,我建议使用相同的解决方案作为解决方法,因为无法提供更好的错误消息。

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)
                         ^

这种技术(隐藏在我们希望在潜在歧义的情况下找不到的隐含的预期模糊隐含)通常是适用的,但显然是相当重量级的...另外一个原因应该避免类型不等式,如果有的话可能的。