为什么玩-json Reads
特征未被声明为协变:
trait Reads[+A]
相关要点: https://gist.github.com/robertberry/9410272
协方差/逆变是否会干扰隐含?
或者,如何写 Reads
密封特征的实例? https://gist.github.com/phadej/c60912802dc494c3212b
为什么玩-json Reads
特征未被声明为协变:
trait Reads[+A]
相关要点: https://gist.github.com/robertberry/9410272
协方差/逆变是否会干扰隐含?
或者,如何写 Reads
密封特征的实例? https://gist.github.com/phadej/c60912802dc494c3212b
它可能是协变的,尤其是当您查看时 Reads[A]
只是一种更丰富的形式 JsValue => A
。
但....含蓄。
Reads[A]
不仅仅是 一个 转换的方式 JsValue
至 A
, 它是 该 办法。
所以,如果我们有
sealed trait Foo
case class Bar(a: Int)
case class Baz(b: Int)
如果你定义了一个 Reads[Bar]
,你也(有协方差)有一个 Reads[Foo]
。
这可能有点奇怪。
object Foo {
implicit reads: Reads[Foo] =
implicitly[Reads[Bar]].orElse[implicitly[Reads[Baz]]]
}
object Bar {
implicit reads = Json.reads[Bar] // {"a":0}
}
object Baz {
implicit reads = Json.reads[Baz] // {"b":0}
def blah(jsValue: JsValue): Foo = jsValue.as[Foo]
}
object Main {
def blah(jsValue: JsValue): Foo = jsValue.as[Foo]
}
发生了什么事 Baz.blah
和 Main.blah
?前者使用 Baz.reads
,后者使用 Foo.reads
,因为(复杂的)隐式解析顺序。
这是一个边缘情况,我仍然认为你可以为协方差做出一个很好的论据,但它确实显示了“事情可以解析JSON到 Foo
“和”可以将JSON解析为所有可能的东西 Foo
”。
它可能是协变的,尤其是当您查看时 Reads[A]
只是一种更丰富的形式 JsValue => A
。
但....含蓄。
Reads[A]
不仅仅是 一个 转换的方式 JsValue
至 A
, 它是 该 办法。
所以,如果我们有
sealed trait Foo
case class Bar(a: Int)
case class Baz(b: Int)
如果你定义了一个 Reads[Bar]
,你也(有协方差)有一个 Reads[Foo]
。
这可能有点奇怪。
object Foo {
implicit reads: Reads[Foo] =
implicitly[Reads[Bar]].orElse[implicitly[Reads[Baz]]]
}
object Bar {
implicit reads = Json.reads[Bar] // {"a":0}
}
object Baz {
implicit reads = Json.reads[Baz] // {"b":0}
def blah(jsValue: JsValue): Foo = jsValue.as[Foo]
}
object Main {
def blah(jsValue: JsValue): Foo = jsValue.as[Foo]
}
发生了什么事 Baz.blah
和 Main.blah
?前者使用 Baz.reads
,后者使用 Foo.reads
,因为(复杂的)隐式解析顺序。
这是一个边缘情况,我仍然认为你可以为协方差做出一个很好的论据,但它确实显示了“事情可以解析JSON到 Foo
“和”可以将JSON解析为所有可能的东西 Foo
”。
假设 Reads
是协变的。我有一个简单的类型层次结构:
sealed trait Foo { def name: String }
case class Bar(name: String, i: Int) extends Foo
case class Baz(name: String, c: Char) extends Foo
还有一个 Reads
其中一个案例类的实例:
import play.api.libs.functional.syntax._
import play.api.libs.json._
implicit val readsBar: Reads[Bar] = (
(__ \ 'name).read[String] and (__ \ 'i).read[Int]
)(Bar.apply _)
但 Bar <: Foo
所以 Reads[Bar] <: Reads[Foo]
,这没有任何意义 - 我还没有说过如何解码 Baz
,所以我显然实际上没有 Reads[Foo]
。
一个更好的问题可能是为什么 Reads
不是逆变的。