2 votes

Comment personnaliser le message implicite "Not Found" ?

J'aimerais remplacer le message standard "implicit not found" (implicite non trouvé) lors de l'utilisation de la fonction =:= dans l'exemple suivant :

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]
}

Si j'essaie de construire un objet illégal comme celui-ci :

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

Je reçois les réponses habituelles :

error: Cannot prove that TTrue =:= TFalse.

Je souhaite personnaliser ce message pour qu'il soit plus informatif. J'ai essayé d'utiliser @scala.annotation.implicitNotFound("custom message: blah") mais cela ne semble pas fonctionner.

Existe-t-il un moyen de le faire ?

5voto

Mario Galic Points 3246

Vous pouvez la modifier pour une méthode particulière en insérant une annotation comme suit

def g[A](i: A)(implicit @implicitNotFound("You should not be a ${A}") ev: A =:= Int) = ???

g("") // Error: You should not be a String

mais bien sûr, cela ne fonctionnera que pour cette méthode.

4voto

Ivan Kurchenko Points 3758

Selon le implicitNotFound annotation Scaladoc ( https://www.scala-lang.org/api/2.12.5/scala/annotation/implicitNotFound.html ) :

... ne peut être trouvé, annoter la classe C avec @implicitNotFound.

Ainsi, en cas d'utilisation de =:= qui possède cette anotation, vous ne pouvez pas la surcharger, à moins que vous ne mettiez en œuvre votre propre égalité de type prouvant la classe de type, avec votre propre message d'erreur :

@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]
    }

et l'utiliser :

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

Le message d'erreur qui en résultera sera donc le suivant :

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

J'espère que cela vous aidera !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X