2017-05-15 10 views
11

मैं समझने की कोशिश कर रहा हूं कि एक मामले में वास्तव में एक अंतर्निहित रूपांतरण क्यों काम कर रहा है, लेकिन दूसरे में नहीं।लागू रूपांतरण अजीबता

case class Wrapper[T](wrapped: T) 
    trait Wrapping { implicit def wrapIt[T](x: Option[T]) = x.map(Wrapper(_)) 

    class NotWorking extends Wrapping { def foo: Option[Wrapper[String]] = Some("foo") } 

    class Working extends Wrapping { 
     def foo: Option[Wrapper[String]] = { 
     val why = Some("foo") 
     why 
     } 
    } 

असल में, मैं Option[T] से Option[Wrapper[T]] को एक अंतर्निहित रूपांतरण है, और एक समारोह, कि एक वैकल्पिक स्ट्रिंग है, जिसमें परोक्ष लिपटे हो जाता है देता है परिभाषित करने के लिए कोशिश कर रहा हूँ: यहाँ एक उदाहरण है।

सवाल क्यों, जब मैं (ऊपर NotWorking) Option[String] सीधे वापस जाने के लिए प्रयास करते हैं, मैं एक त्रुटि (found : String("foo") required: Wrapper[String]), कि दूर चला जाता है अगर मैं इसे लौटने से पहले एक वैल के लिए परिणाम आवंटित मिलता है।

क्या देता है?

उत्तर

10

मुझे नहीं पता कि यह इरादा है या एक बग माना जाएगा, लेकिन मुझे लगता है कि यह हो रहा है।

def foo: Option[Wrapper[String]] = Some("foo") में कंपाइलर Some() को Wrapper[String] के रूप में दिए गए तर्क के अपेक्षित प्रकार को सेट करेगा। फिर यह देखता है कि आपने String प्रदान किया है, जो कि अपेक्षित नहीं है, इसलिए यह एक अंतर्निहित रूपांतरण String => Wrapper[String] की तलाश में है, एक नहीं ढूंढ सकता है, और विफल रहता है।

ऐसा क्यों है कि प्रकार सामान की उम्मीद है, और सिर्फ एक रूपांतरण को खोजने के लिए बाद में टाइप नहीं है Some("foo")Some[String] के रूप में और कोशिश की जरूरत है?

case class Invariant[T](t: T) 
val a: Invariant[Any] = Invariant("s") 

इस कोड को काम करने के लिए, संकलक सिर्फ Invariant[String] रूप Invariant("s") टाइप नहीं कर सकते क्योंकि तब संकलन Invariant[String] के रूप में असफल हो जायेगी में की एक उप प्रकार नहीं है: क्योंकि scalac निम्नलिखित कोड typecheck करने में सक्षम होना चाहता है Invariant[Any]। कंपाइलर को अपेक्षित प्रकार "s"Any पर सेट करने की आवश्यकता है ताकि यह देख सके कि "s" बहुत देर हो चुकी है इससे पहले Any का एक उदाहरण है।

इस कोड और आपके कोड दोनों को सही ढंग से काम करने के लिए, मुझे लगता है कि कंपाइलर को किसी प्रकार के बैकट्रैकिंग तर्क की आवश्यकता होगी, जो शायद अच्छे कारणों से नहीं है।

कारण यह है कि आपका Working कोड काम करता है, यह इस प्रकार का प्रकार अनुमान कई लाइनों तक नहीं चलता है। आकस्मिक रूप से val a: Invariant[Any] = {val why = Invariant("s"); why} संकलन नहीं करता है।

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