これは、このタイプの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は、暗黙的なものなしではコンパイルされません。証拠のおかげだとわかっていても、型システムはそうではないからです。あなたはそれをキャストすることができます、それは確実に機能するでしょう:aRoot
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()、関数が関与していることを知る必要はありません。
ただし、型システムは暗黙的のみを使用して anAを aに解決し、 aをaまたは aに解決しJsValueません。Seq[A]Seq[JsValue]Reads[A]Reads[JsValue]
したがって、あなたの場合、何もしない関数を適用することで aが a であるthis.map(witness)ことを型システムに理解させるだけで、 a を取り、 aを返すもので構成できます。Reads[A]Reads[JsValue]JsValueB
詳細については、SO に関する一般化された型制約の質問を参照してください。