这是因为这种类型的witness也是一个函数。它在Predef 中声明为:
sealed abstract class <:<[-From, +To] extends (From => To) with Serializable
所以A <:< JsValue 也是一个函数(A) => JsValue。你可能想知道这个函数做了什么:它什么都不做,它接受 A 并直接返回它(作为 JsValue)。
要了解为什么这很有用,请考虑以下示例:
sealed trait Root { def bip() { println("bip") } }
def makeBip[A <: Root](a: A) {
a.bip() // works because a is known to the type system to be a Root
}
def makeBip2[A](a: A)(implicit ev: A <:< Root) {
a.bip() // works, because implicit resolution turns it into `ev(a).bip()`
}
最后一个方法makeBip2 没有隐式就无法编译,因为即使你知道a 是Root,感谢证据,类型系统却不知道。你可以施放它,它一定会起作用:
def makeBip3[A](a: A)(implicit ev: A <:< Root) {
a.asInstanceOf[Root].bip() // ugly
}
但这感觉不对。如果你有办法将a 转换为Root...但是等等,你可以做到:证据本身!
def makeBip4[A](a: A)(implicit ev: A <:< Root) {
ev(a).bip() // works!
}
而且由于隐式参数可用作方法中的隐式参数,a.bip() 将自动转换为 ev(a).bip(),您无需知道其中涉及到函数。
但是,类型系统仅使用隐式将A 解析为JsValue,而不是将Seq[A] 解析为Seq[JsValue] 或将Reads[A] 解析为Reads[JsValue]。
所以在你的情况下,this.map(witness) 只是让类型系统明白 Reads[A] 是 Reads[JsValue] 通过应用什么都不做的函数,以便它可以与需要 JsValue 和返回B。
有关更多信息,请参阅关于 SO 的Generalized type constraits 问题。