如何自定义隐式找不到消息

问题描述 投票:1回答:1

在以下示例中,使用=:=运算符时,我想替换标准的隐式未找到消息:

sealed trait TBoolean
sealed trait TTrue extends TBoolean
sealed trait TFalse extends TBoolean

class Builder[X <: TBoolean, Y <: TBoolean, Z <: TBoolean] private(x: Int, y: Int, z: List[List[Int]]) {
  protected def this() = this(-1, -1, List.empty)

  def withX(xx: Int)(implicit ev: X =:= TFalse) = new Builder[TTrue, Y, Z](xx, this.y, this.z)

  def withY(yy: Int)(implicit ev: Y =:= TFalse) = new Builder[X, TTrue, Z](this.x, yy, this.z)

  def withZ(zz: List[List[Int]])(implicit ev: Z =:= TFalse) = new Builder[X, Y, TTrue](this.x, this.y, zz)

  def build()(implicit ev1: Y =:= TTrue, ev2: X =:= TTrue, ev3: Z =:= TTrue) = println(s"${x} ${y} ${z}")
}

object Builder {
  def apply() = new Builder[TFalse, TFalse, TFalse]
}

如果我尝试构建这样的非法对象:

Builder().withX(1).withY(1).withZ(List.empty).withY(1).build   // i.e. two withY calls

我照常:

error: Cannot prove that TTrue =:= TFalse.

我想自定义此消息,以便提供更多信息。我尝试使用@scala.annotation.implicitNotFound("custom message: blah"),但似乎不起作用。

有没有办法做到这一点?

scala
1个回答
0
投票

根据implicitNotFound注释Scaladoc(https://www.scala-lang.org/api/2.12.5/scala/annotation/implicitNotFound.html):

...找不到,用@implicitNotFound注释the class C。

因此,如果使用带有此注释的=:=类,则无法覆盖它,除非您将使用自己的错误消息实现自己的类型相等证明类型类:

@implicitNotFound(msg = "Custom type equals prove message ${From} =::= ${To}.")
    sealed abstract class =::=[From, To]
    private final val singleton_=::= = new =::=[Any,Any] {}
    object =::= {
      implicit def tpEquals[A]: A =::= A = singleton_=::=.asInstanceOf[A =::= A]
    }

并使用它:

def withZ(zz: List[List[Int]])(implicit ev: Z =::= TFalse)

所以结果错误消息将是:

Custom type equals prove message TTrue =::= TFalse.

希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.