2014-08-29 11 views
11

क्यों खेलते-json Reads विशेषता घोषित नहीं किया गया है covariant:रीड्स को कॉन्वेंट नहीं घोषित किया गया है?

trait Reads[+A] 

संबंधित सार: https://gist.github.com/robertberry/9410272

सहप्रसरण/contravariance implicits के साथ हस्तक्षेप करता है?

या वैकल्पिक रूप से, सीलबंद लक्षणों के लिए Reads उदाहरण कैसे लिखें? https://gist.github.com/phadej/c60912802dc494c3212b

उत्तर

1

यह कॉन्वेंटेंट हो सकता है, खासकर जब आप Reads[A] को JsValue => A के एक समृद्ध रूप के रूप में देखते हैं।

लेकिन .... implicitness

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 का उपयोग करता है।

यह बढ़त मामला है, और मैं अभी भी लगता है कि आप सहप्रसरण के लिए एक अच्छा तर्क कर सकता है, लेकिन यह बीच का अंतर दिखाने करता है "बात संभवतः Foo में JSON पार्स कर सकते हैं" और "बात यह है कि सभी में JSON पार्स कर सकते हैं संभव Foo "।

+0

धन्यवाद, निहितार्थ मामला है, जैसा कि मैंने सोचा था। क्या आप जिस्ट पर टिप्पणी कर सकते हैं। आपकी राय क्या है, क्या कोई लिखना चाहिए [चाइल्ड]। मैप (x => x) 'या' पढ़ता है [चाइल्ड] .as [पढ़ता है [अभिभावक]] ', क्या बाद में कुछ गलत हो सकता है? – phadej

+0

@ फीडेज, क्या आपका मतलब '.asInstanceOf' है? किसी भी मामले में, मुझे नहीं लगता कि इस प्रकार के विस्तार के साथ कुछ भी बुरा है। एकमात्र समस्या यह है कि यह स्वचालित रूप से implicits के लिए किया जाता है। –

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], और यह कोई बनाता है भावना-मैं नहीं है Baz को डीकोड करने के तरीके के बारे में कुछ भी कहा, इसलिए मुझे स्पष्ट रूप से Reads[Foo] नहीं है।

एक बेहतर सवाल यह हो सकता है कि Reads contravariant क्यों नहीं है।

+0

लेकिन अगर मेरे पास गैर-निहित 'पढ़ता है बार: पढ़ता है [बार]', और 'पढ़ता है: पढ़ता है [बाज़]': फिर 'readsFoo = readsBar या पढ़ता है Baz' काम नहीं करता है। हालांकि 'readsFoo = readsBar.map (x => x) या पढ़ता है Baz.map (x => x)' ठीक है। यहां मैं कॉन्वेंट मानचित्र देखता हूं। – phadej

+0

यह अभी भी मुझे परेशान करता है, मैंने उम्मीद की है कि समस्या को स्पष्ट रूप से स्पष्ट करने के लिए मैंने एक छोटा सा लिखा है: https://gist.github.com/phadej/c60912802dc494c3212b – phadej

+0

मुझे यह स्पष्टीकरण पर्याप्त नहीं है। आपके पास अभी भी JSON को 'Foo' में अनुवाद करने का एक तरीका है, इसलिए, 'पढ़ता है [बार] '* है * एक' पढ़ता है [Foo]'। –

संबंधित मुद्दे