2015-09-30 5 views
6

मुझे स्कैला में टाइपक्लास के साथ कुछ समस्याएं आ रही हैं और एक टाइपक्लास उदाहरण नहीं मिलने पर संकलन समय में त्रुटियों के साथ ठीक है। आइए मान लें कि मेरे पास टाइपक्लास TC और ऑब्जेक्ट B[C] है जिसमें TC का उदाहरण है, केवल C में TC का उदाहरण है। स्कैला में इसे implicit def btc[C](implicit ctc: TC[C]) = new TC[B[C]] { ... } लिखा जा सकता है। जब आपको C के लिए TC[B[C]] की आवश्यकता होती है जिसके लिए स्केलैक को TC[C] कोई उदाहरण नहीं मिल रहा है, तो स्केलैक यह कहने में त्रुटि देगा कि उसे TC[B[C]] नहीं मिल रहा है। हालांकि यह सच है, त्रुटि संदेश में कारण है कि स्केलैक TC[B[C]] नहीं ढूंढ सकता है, यह है कि यह TC[C] नहीं ढूंढ सकता है।स्कैला के निहित नॉटफॉउंड एनोटेशन को अधिक सटीक बनाएं

समस्या समझने के लिए, मैं एक छोटे से खिलौना उदाहरण है जहाँ TCPrettyPrintable है बनाने का फैसला किया, CUnit है और BOption है:

import scala.annotation.implicitNotFound 

@implicitNotFound("Cannot pretty print instances of the type ${T}") 
trait PrettyPrintable[T] { 
    def prettyPrint(t: T): String 
} 

object PrettyPrintable { 
    def apply[T](implicit pp: PrettyPrintable[T]): PrettyPrintable[T] = pp 

    implicit def optPP[T](implicit opp: PrettyPrintable[T]) = new PrettyPrintable[Option[T]] { 
    override def prettyPrint(ot: Option[T]): String = ot.fold("")(opp.prettyPrint) 
    } 
} 

object Main extends App { 
    println(PrettyPrintable[Option[Unit]].prettyPrint(None)) // error 
} 

अगर मैं आवेदन चलाने के लिए, मैं त्रुटि मिलती है:

[error] /home/rief/prog/scala/implicitNotFoundTest/Main.scala:24: Cannot pretty print instances of the type Option[Unit] 
[error] println(PrettyPrintable[Option[Unit]].prettyPrint(None)) 

यह निश्चित रूप से सच है: स्केलैक Option[Unit] प्रकार के लिए एक सुंदर प्रिंट उदाहरण नहीं ढूंढ सकता है। समस्या यह है कि त्रुटि स्वयं बहुत उपयोगी नहीं है क्योंकि बिंदु यह नहीं है कि स्केलेक को टाइप क्लास का उदाहरण नहीं मिल रहा है, लेकिन इसे और क्यों नहीं मिल रहा है। इस मामले में, Option[Unit] का एक सुंदर प्रिंट उदाहरण नहीं है क्योंकि Unit में एक सुंदर प्रिंट उदाहरण नहीं है लेकिन अधिक जटिल मामलों के लिए यह एक दुःस्वप्न हो सकता है।

मेरा प्रश्न है: क्या अंतर्निहित त्रुटियों को त्रुटियों को और सटीक नहीं पाया जा सकता है?

+0

यह एक अच्छा है। मैंने एक बार विचार किया था कि एनोटेशन स्ट्रिंग के लिए एक इंटरपोलेटर को किस संदर्भ में उजागर करना है, लेकिन मैंने स्पष्ट खोज इतिहास के बारे में सोचा नहीं था। https://issues.scala-lang.org/browse/SI-7411 –

उत्तर

0

यह अच्छा होगा, लेकिन मुझे लगता है कि जिस समस्या को आप हल करना चाहते हैं वह पहले ब्लश पर दिखाई देने से अधिक जटिल है। इस उदाहरण में, मैं PrettyPrintable के लिए कुछ और निहित Vals और defs जोड़ दिया है:

import scala.annotation.implicitNotFound 

@implicitNotFound("Cannot pretty print instances of the type ${T}") 
trait PrettyPrintable[T] { 
    def prettyPrint(t: T): String 
} 

object PrettyPrintable { 
    def apply[T](implicit pp: PrettyPrintable[T]): PrettyPrintable[T] = pp 

    implicit val intPP = new PrettyPrintable[Int] { 
    override def prettyPrint(i: Int): String = s"== $i ==" 
    } 

    implicit def optPP[T](implicit opp: PrettyPrintable[T]) = new PrettyPrintable[Option[T]] { 
    override def prettyPrint(ot: Option[T]): String = s"-- ${ot.map(opp.prettyPrint)} --" 
    } 

    implicit def pairPP[T, U](implicit tpp: PrettyPrintable[T], upp: PrettyPrintable[U]) = 
    new PrettyPrintable[(T, U)] { 
     override def prettyPrint(pair: (T, U)): String = 
     s"[[[ ${tpp.prettyPrint(pair._1)} >>> ${upp.prettyPrint(pair._2)} ]]]" 
    } 

} 

object Main extends App { 
    println(PrettyPrintable[Int].prettyPrint(6))     // prints == 6 == 
    println(PrettyPrintable[Option[Int]].prettyPrint(None))  // prints -- None -- 
    println(PrettyPrintable[Option[Int]].prettyPrint(Some(6)))  // prints -- Some(== 6 ==) -- 
    println(PrettyPrintable[(Int,Int)].prettyPrint((6 -> 7)))  // prints [[[ == 6 == >>> == 7 == ]]] 
    println(PrettyPrintable[(Float,Long)].prettyPrint((6F -> 7L))) // error 
} 

अंतिम पंक्ति अपने उदाहरण से निम्नलिखित संकलक त्रुटि, त्रुटि के अनुरूप उत्पादन करता है:

Cannot pretty print instances of the type (Float, Long) 

में अपने मामला, एक अंतर्निहित PrettyPrintable[Unit] नहीं ढूंढने पर एक अंतर्निहित PrettyPrintable[Option[Unit]] नहीं ढूंढने के लिए दोष डालना आसान है। लेकिन जोड़ी के मामले में, क्या आप एक अंतर्निहित PrettyPrintable[Float] नहीं ढूंढने पर एक अंतर्निहित PrettyPrintable[(Float, Long)] नहीं ढूंढना चाहते हैं, एक अंतर्निहित PrettyPrintable[Long], या दोनों नहीं ढूंढ रहे हैं?

ध्यान दें कि निहित रिज़ॉल्यूशन विफलता के मूल कारण के मूल के समान आकार भी नहीं हो सकता है। , मूल कारण एक अंतर्निहित Int नहीं मिल रहा है, या एक अंतर्निहित String नहीं मिल

implicit def i2ppf(implicit i: Int) = new PrettyPrintable[Float] { 
    override def prettyPrint(f: Float): String = s"xx $f xx" 
} 

implicit def s2ppf(implicit s: String) = new PrettyPrintable[Float] { 
    override def prettyPrint(f: Float): String = s"xx $f xx" 
} 

अब: उदाहरण के लिए, निम्न दो अंतर्निहित defs जोड़ने पर विचार करें? वास्तविक जवाब बहुत जटिल है।कुछ इस तरह:

  • वहाँ था कोई अंतर्निहित PrettyPrintable[(Float,Long)] है क्योंकि:
    • वहाँ कि सटीक प्रकार के साथ कोई निहित मूल्य, और
    • दोनों PrettyPrintable[Float] और PrettyPrintable[Long]
      • के लिए implicits नहीं थे PrettyPrintable[Float] के लिए कोई अंतर्निहित नहीं था क्योंकि:
        • कि सटीक प्रकार के साथ कोई अंतर्निहित मूल्य था, और
        • कोई अंतर्निहित Int था, और
        • वहाँ था कोई अंतर्निहित String
      • वहाँ PrettyPrintable[Long] के लिए कोई निहित था क्योंकि:
          वहाँ
        • उस सटीक प्रकार
    • के साथ कोई अंतर्निहित मूल्य नहीं था

अपने प्रश्न का उत्तर में, मुझे लगता है कि आप आप के लिए संभावनाओं की एक विस्तृत पेड़ से प्रोग्रामेटिक एक्सेस के कुछ प्रकार प्रदान शामिल होगा "यह संभव अंतर्निहित पर त्रुटियों और अधिक सटीक नहीं मिला बनाने के लिए है?", सामान्य मामले में एक त्रुटि संदेश को अधिक सटीक बनाने के लिए। नौकरी के लिए सिर्फ एक सभ्य एपीआई डिजाइन करना एक बहुत प्रभावशाली उपक्रम होगा, अकेले उस एपीआई के कार्यान्वयन को छोड़ दें।

+0

कंपाइलर प्रदर्शन कारणों से उपर्युक्त पेड़ों को भी छीन सकता है। उदाहरण के लिए, संकलक शायद 'प्रीटीप्रिंटेबल [लांग]' के लिए प्रत्यारोपण पर विचार नहीं करता था, जब वह 'प्रीटीप्रिंटेबल [फ्लोट] ' –

+0

के लिए निहित नहीं पाया गया था, मुझे नहीं लगता कि सवाल काफी जटिल है। 'पीपी [(फ्लोट, लांग)] के मामले में, आदर्श रूप से त्रुटि संदेश इंगित करेगा कि दो उदाहरणों में से कौन सा उदाहरण गुम है, या दोनों, अगर ऐसा है। और आपके बाद के उदाहरण अंतर्निहित रूपांतरण हैं जो एक ऐसा फॉर्म लेते हैं जिसे आप सामान्य रूप से टाइप क्लास के साथ काम करते समय नहीं देखते हैं। –

+0

@TravisBrown क्या आप ऐसे समाधान का प्रस्ताव देना चाहते हैं जो सामान्य मामले को संभालेगा? यहां तक ​​कि साधारण मामले में आप प्रस्तावित करते हैं कि त्रुटि संदेश को "इंगित करना चाहिए कि दो में से कौन से उदाहरण गुम हैं, या दोनों, अगर ऐसा है", तो आप इस तरह के एक त्रुटि संदेश को कैसे बनाने जा रहे हैं? आप इसे कितने दूर ले जा रहे हैं? क्या आप 'पीपी [(((ए, बी), (सी, डी), ई), (एफ, जी) को संभालने जा रहे हैं)] '? –

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