加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使Scala的implicitNotFound注释更精确

发布时间:2020-12-16 19:14:23 所属栏目:安全 来源:网络整理
导读:我在 Scala中遇到了类型类的问题,更准确地说,在编译时无法找到类型类实例时出现错误.假设我有一个类型类TC和一个对象B [C],只有当C有一个TC实例时才有一个TC实例.在Scala中,这可以写成隐式def btc [C](隐式ctc:TC [C])= new TC [B [C]] {…}.当你需要TC的一
我在 Scala中遇到了类型类的问题,更准确地说,在编译时无法找到类型类实例时出现错误.假设我有一个类型类TC和一个对象B [C],只有当C有一个TC实例时才有一个TC实例.在Scala中,这可以写成隐式def btc [C](隐式ctc:TC [C])= new TC [B [C]] {…}.当你需要TC的一个TC [B [C]],scalac找不到实例TC [C]时,scalac会给出一个错误,说它找不到TC [B [C]].虽然这是真的,但是错误消息缺少scalac无法找到TC [B [C]]的原因,即它无法找到TC [C].

为了说明这个问题,我决定制作一个小玩具示例,其中TC为PrettyPrintable,C为Unit,B为选项:

import scala.annotation.implicitNotFound

@implicitNotFound("Cannot pretty print instances of the type ${T}")
trait PrettyPrintable[T] {
  def prettyPrint(t: T): String
}

object PrettyPrintable {
  def apply[T](implicit pp: PrettyPrintable[T]): PrettyPrintable[T] = pp

  implicit def optPP[T](implicit opp: PrettyPrintable[T]) = new PrettyPrintable[Option[T]] {
    override def prettyPrint(ot: Option[T]): String = ot.fold("")(opp.prettyPrint)
  }
}

object Main extends App {
  println(PrettyPrintable[Option[Unit]].prettyPrint(None)) // error
}

如果我运行该应用程序,我收到错误:

[error] /home/rief/prog/scala/implicitNotFoundTest/Main.scala:24: Cannot pretty print instances of the type Option[Unit]
[error]   println(PrettyPrintable[Option[Unit]].prettyPrint(None))

这当然是正确的:scalac找不到类型为Option [Unit]的漂亮的打印实例.问题是错误本身并不是很有用,因为重点不在于scalac找不到类型类的实例,而是找不到它的原因.在这种情况下,Option [Unit]没有漂亮的打印实例的原因是因为Unit没有漂亮的打印实例,但对于更复杂的情况,这可能是一场噩梦.

我的问题是:是否有可能使隐含的错误更加精确?

解决方法

那会很好,但我认为你想要解决的问题比初看起来时要复杂得多.在这个例子中,我为PrettyPrintable添加了一些更隐式的val和defs:

import scala.annotation.implicitNotFound

@implicitNotFound("Cannot pretty print instances of the type ${T}")
trait PrettyPrintable[T] {
  def prettyPrint(t: T): String
}

object PrettyPrintable {
  def apply[T](implicit pp: PrettyPrintable[T]): PrettyPrintable[T] = pp

  implicit val intPP = new PrettyPrintable[Int] {
    override def prettyPrint(i: Int): String = s"== $i =="
  }

  implicit def optPP[T](implicit opp: PrettyPrintable[T]) = new PrettyPrintable[Option[T]] {
    override def prettyPrint(ot: Option[T]): String = s"-- ${ot.map(opp.prettyPrint)} --"
  }

  implicit def pairPP[T,U](implicit tpp: PrettyPrintable[T],upp: PrettyPrintable[U]) =
    new PrettyPrintable[(T,U)] {
      override def prettyPrint(pair: (T,U)): String =
        s"[[[ ${tpp.prettyPrint(pair._1)} >>> ${upp.prettyPrint(pair._2)} ]]]"
    }

}

object Main extends App {
  println(PrettyPrintable[Int].prettyPrint(6))                   // prints == 6 ==
  println(PrettyPrintable[Option[Int]].prettyPrint(None))        // prints -- None --
  println(PrettyPrintable[Option[Int]].prettyPrint(Some(6)))     // prints -- Some(== 6 ==) --
  println(PrettyPrintable[(Int,Int)].prettyPrint((6 -> 7)))      // prints [[[ == 6 == >>> == 7 == ]]]
  println(PrettyPrintable[(Float,Long)].prettyPrint((6F -> 7L))) // error
}

最后一行产生以下编译器错误,类似于示例中的错误:

Cannot pretty print instances of the type (Float,Long)

在你的情况下,很容易因未找到隐含的PrettyPrintable [Unit]而找不到隐含的PrettyPrintable [Option [Unit]].但是对于这对,你想要责备没有找到隐含的PrettyPrintable [(Float,Long)]没有找到隐含的PrettyPrintable [Float],没有找到隐含的PrettyPrintable [Long],或两者兼而有之?

请注意,隐式解析失败的根本原因甚至可能与原始解析失败的形状不同.例如,考虑添加以下两个隐式defs:

implicit def i2ppf(implicit i: Int) = new PrettyPrintable[Float] {
  override def prettyPrint(f: Float): String = s"xx $f xx"
}

implicit def s2ppf(implicit s: String) = new PrettyPrintable[Float] {
  override def prettyPrint(f: Float): String = s"xx $f xx"
}

现在,根本原因是找不到隐式Int,还是找不到隐式String?实际答案非常复杂.像这样的东西:

>没有隐含的PrettyPrintable [(Float,Long)]因为:

>对于那种精确类型,AND没有隐含的值
> PrettyPrintable [Float]和PrettyPrintable [Long]都没有暗示

> PrettyPrintable [Float]没有暗示,因为:

>对于那种精确类型,AND没有隐含的值
>没有隐含的Int,AND
>没有隐含的字符串

> PrettyPrintable [Long]没有隐含的原因,因为:

>该精确类型没有隐含值

在回答你的问题时,“是否有可能使隐含的错误更加精确?”,我认为这将涉及为您提供某种程序化访问,以便您更准确地构造错误消息.一般情况.只为这项工作设计一个不错的API将是一项非常令人印象深刻的工作,更不用说该API的实现了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读