爲什麼玩JSON的Reads
特質不宣協:爲什麼Reads沒有聲明協變?
trait Reads[+A]
相關要點:https://gist.github.com/robertberry/9410272
是否協方差/逆變干擾implicits?
或者可選地,如何編寫密封特徵的Reads
實例? https://gist.github.com/phadej/c60912802dc494c3212b
爲什麼玩JSON的Reads
特質不宣協:爲什麼Reads沒有聲明協變?
trait Reads[+A]
相關要點:https://gist.github.com/robertberry/9410272
是否協方差/逆變干擾implicits?
或者可選地,如何編寫密封特徵的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
是協變的。我有一個簡單的類型層次:
sealed trait Foo { def name: String }
case class Bar(name: String, i: Int) extends Foo
case class Baz(name: String, c: Char) extends Foo
而對於case類的一個實例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
不是逆變。
但是,如果我有非隱式的'readsBar:Reads [Bar]'和'readsBaz:Reads [Baz]':那麼'readsFoo = readsBar或Else readsBaz'不起作用。但是'readsFoo = readsBar.map(x => x)或者elsese readsBaz.map(x => x)'是可以的。在這裏我看到了協變映射。 – phadej 2014-08-29 18:24:04
這仍然困擾我,我寫了一個小小的要點,希望澄清這個問題:https://gist.github.com/phadej/c60912802dc494c3212b – phadej 2014-10-08 17:59:18
我不這樣解釋就夠了。你仍然有一種將JSON轉換爲'Foo'的方式,所以'Reads [Bar]'*'是* Reads [Foo]'。 – 2015-10-04 01:49:00
謝謝,暗示就是這樣,就像我想的那樣。你能評論一下這個要點嗎?如果你寫一個'讀取[Child] .map(x => x)'或'讀取[Child] .as [Reads [Parent]]',你的意見是什麼? – phadej 2015-10-05 07:49:23
@phadej,你的意思是'.asInstanceOf'?無論如何,我認爲擴展類型並不是什麼壞事。唯一的問題是如果它是自動完成的。 – 2015-10-05 13:32:18