2014-08-29 6 views

답변

1

특히 Reads[A]을 더 부유 한 형태의 JsValue => A으로 볼 때 공분산 될 수 있습니다.

하지만 .... implicitness.

Reads[A]뿐만 아니라 단지 AJsValue에서 변환하는 방법, 그것은 방법입니다.

그래서 당신이 Reads[Bar]을 정의한 경우 우리가

sealed trait Foo 
case class Bar(a: Int) 
case class Baz(b: Int) 

이 있다면, 당신은 또한 (공분산)와 함께 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.blahMain.blah에 무슨 일? 전자는 Baz.reads을 사용하고 후자는 암시 적 해석 순서 (복잡한) 때문에 Foo.reads을 사용합니다.

이것은 가장 중요한 사례이며, 여전히 공분산에 대한 좋은 논거를 할 수 있다고 생각하지만, "JSON을 구문 분석 할 가능성이 있습니다 (Foo)"와 "JSON을 모두 구문 분석 할 수있는 것 가능 Foo ".

+0

감사합니다. 내 생각에 암시가있는 경우입니다. 당신은 요점에 대해 논평 할 수 있습니까? 당신이 생각하기에,''[Child] .map (x => x)'또는'[Child] .as [Reads [Parent]]'라고 쓰면, 후자에서 뭔가 잘못 될 수 있습니까? – phadej

+0

@phadej,'.asInstanceOf'를 의미합니까? 어쨌든, 나는 타입을 확장하는 것에 나쁜 것이 있다고 생각하지 않는다. 유일한 문제는 암시에 대해 자동으로 수행되는 경우입니다. –

8

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]을,이 더하지 않습니다 감각을-I하지 않았습니다 Baz을 디코딩하는 방법에 대해 언급 했으므로 분명히 실제로는 Reads[Foo]이 없습니다.

더 좋은 질문은 왜 Reads이 반공사가 아닌지입니다.

+0

하지만 암시 적이 아닌'readsBar : Read [Bar]'및'readsBaz : Reads [Baz]': 그러면'readsFoo = readsBar 또는Else readsBaz'가 작동하지 않습니다. 그러나'readsFoo = readsBar.map (x => x) orElse readsBaz.map (x => x)'는 괜찮습니다. 여기에 공변량지도가 있습니다. – phadej

+0

이것은 여전히 ​​귀찮다. 문제를 명확히 밝히기 위해 작은 요점을 썼다. https://gist.github.com/phadej/c60912802dc494c3212b – phadej

+0

나는이 설명이 충분하지 않다. JSON을'Foo'로 번역 할 수있는 방법이 있습니다. 그래서'Reads [Bar]'*는''Reads [Foo]'입니다. –