2012-10-28 22 views
8

यह निम्न कीड़े मुझे:त्रुटि: डिफ़ॉल्ट तर्क के साथ बहुरूपी अभिव्यक्ति

trait Foo[A] 
class Bar[A](set: Set[Foo[A]] = Set.empty) 

यह पैदावार

<console>:8: error: polymorphic expression cannot be instantiated to expected type; 
found : [A]scala.collection.immutable.Set[A] 
required: Set[Foo[?]] 
     class Bar[A](set: Set[Foo[A]] = Set.empty) 
             ^

यह काफी कष्टप्रद मैं Set.empty में प्रकार पैरामीटर को दोहराने के लिए होता है। इस डिफ़ॉल्ट तर्क के साथ प्रकार अनुमान विफल क्यों होता है? निम्नलिखित काम करता है:

class Bar[A](set: Set[Foo[A]] = { Set.empty: Set[Foo[A]] }) 

कृपया ध्यान दें कि यह विशेष रूप से Set साथ कोई संबंध नहीं है:

case class Hallo[A]() 
class Bar[A](hallo: Hallo[A] = Hallo.apply) // nope 

अजीब न केवल इस काम करता है:

class Bar[A](hallo: Hallo[A] = Hallo.apply[A]) 

... लेकिन यह भी:

class Bar[A](hallo: Hallo[A] = Hallo())  // ??? 
+2

कोई जवाब नहीं है, लेकिन तीन चीजें ध्यान देने योग्य हैं: आप 'ए' के ​​अलावा किसी अन्य प्रकार के पैरामीटर को नामित करना चाहते हैं ताकि 'मिली' में 'अलग' 'ए' के ​​साथ भ्रम से बचने के लिए: [ए] scala.collection। अपरिवर्तनीय। सेट [ए] 'संदेश; 'सेट' और आपके 'हेलो' दोनों के बारे में महत्वपूर्ण तथ्य यह है कि वे अचूक हैं (जैसा कि 'सूची' कहने के विपरीत) है; और आपकी आखिरी पंक्ति संकलन संभवतः वह नहीं करता जो आप चाहते हैं। –

+1

जबकि 'कक्षा बार [ए] (हेलो: हेलो [ए] = हेलो.प्ली)' यदि आप इसे 'Hallo.apply()' का उपयोग करने के लिए बदलते हैं तो यह ठीक काम करता है। आप _should_ माता-पिता को छोड़ने में सक्षम हो सकते हैं, इसलिए इसे वास्तव में यहां भ्रमित होना चाहिए। ऐसा लगता है कि आप बिना किसी तर्क के 'आवेदन' को कॉल करने के बजाय आंशिक रूप से लागू फ़ंक्शन 'Hallo.apply' गुजर रहे हैं। (त्रुटि संदेश कहता है कि यह टाइप '[ए]() हेलो [ए]'।) – DaoWen

उत्तर

5

आप बल्कि कोष्ठक/ब्रेसिज़ के अतिरिक्त सेट और प्रकार टिप्पणी जोड़ने के लिए की तुलना में empty विधि पर सीधे प्रकार निर्दिष्ट कर सकते हैं:

class Bar[A](set: Set[Foo[A]] = Set.empty[Foo[A]]) 

क्यों प्रकार निष्कर्ष में विफल रहता है के रूप में, इन सवालों को देखने के :

अद्यतन:

मैं माफी माँगता हूँ, मेरे जल्दबाजी जवाब तरह से बंद किया गया था। उपरोक्त पदों में मुद्दा वास्तव में इस मुद्दे से संबंधित नहीं है। @TravisBrown ने उपरोक्त अपनी टिप्पणी में एक बहुत अच्छा मुद्दा बना दिया। यह पहली बार में काम करने के लिए प्रकट होता है:

class Bar[A](set: Set[A] = Set.empty) 

लेकिन आप वास्तव में निर्माता यह उपयोग-स्थल पर विफल रहता है फोन करने की कोशिश करता है, तो:

new Bar[Int] 
// <console>:9: error: type mismatch; 
// found : scala.collection.immutable.Set[Nothing] 
// required: Set[Int] 
// Note: Nothing <: Int, but trait Set is invariant in type A. 
// You may wish to investigate a wildcard type such as `_ <: Int`. (SLS 3.2.10) 
// Error occurred in an application involving default arguments. 
//    new Bar[Int] 

यह पता चलता है कि संकलक करने के लिए डिफ़ॉल्ट पैरामीटर के लिए मजबूर नहीं करता है सभी A के लिए सभी A के लिए मान्य रहें। वे शायद यह चुनाव किया ताकि आप कुछ इस तरह कर सकते हैं:

class Bar[A](set: Set[Option[A]] = Set.empty) 
// <console>:7: error: polymorphic expression cannot be instantiated to expected type; 
// found : [A]scala.collection.immutable.Set[A] 
// required: Set[Option[?]] 
//  class Bar[A](set: Set[Option[A]] = Set.empty) 

:

scala> case class MyClass[T](set: Set[T] = Set(0)) 
defined class MyClass 

scala> MyClass() // defaults to MyClass[Int] 
res0: MyClass[Int] = MyClass(Set(0)) 

scala> MyClass(Set('x)) // but I can still use other types manually 
res1: MyClass[Symbol] = MyClass(Set('x)) 

हालांकि, पैरामिट्रीकृत प्रकार के साथ घोंसला बनाने से किसी भी प्रकार का टाइप करने के लिए निर्माता में घोषणा स्थल पर जाँच में विफल रहता है क्योंकि संकलक सह के रूप में Nothing का चयन करता है

class Bar[ A ](set: List[Foo[A]] = List.empty) // OK 

class Bar[ A ](set: Map[Int,Foo[A]] = Map.empty) // OK (unless you use it) 

class Bar[ A ](set: Map[Foo[A],Int] = Map.empty) // BAD 
// <console>:8: error: polymorphic expression cannot be instantiated to expected type; 
// found : [A, B]scala.collection.immutable.Map[A,B] 
// required: Map[Foo[?],Int] 
//   class Bar[ A ](set: Map[Foo[A],Int] = Map.empty) // BAD 
//              ^

ये काम कर रहे हैं: निष्कर्ष यदि प्रकार पैरामीटर एक covariant स्थिति में है विफल नहीं डिफ़ॉल्ट रूप से संस्करण प्रकार।यह List के लिए ठीक काम करता है, लेकिन उपरोक्त दूसरा उदाहरण काम नहीं करता है यदि आप वास्तव में इसे कॉल करने का प्रयास करते हैं।

इस अजीबता का अधिकांश कारण शायद स्केल डिफ़ॉल्ट तर्कों को संभालने का तरीका है। कंपाइलर स्वचालित रूप से साथी ऑब्जेक्ट में एक अतिरिक्त विधि जोड़ता है, और फिर जहां भी आप एक तर्क छोड़ देते हैं, संकलक स्वचालित रूप से गायब तर्क उत्पन्न करने के लिए साथी ऑब्जेक्ट में नई विधि में एक विधि कॉल जोड़ता है। ऐसा लगता है कि एक विधि में डिफ़ॉल्ट तर्क को सारणीबद्ध करना कुछ चीजों को टाइप अनुमान में विभाजित करता है जो सामान्य असाइनमेंट के साथ काम करेगा।

मुझे लगता है कि इनमें से अधिकतर निष्कर्ष बहुत भ्रमित हैं। इससे मैं क्या लेता हूं यह है कि वास्तव में यह सुनिश्चित करने के लिए अपने डिफ़ॉल्ट मानकों का परीक्षण करना महत्वपूर्ण है कि जब आप उनका उपयोग करने का प्रयास करते हैं तो वे सहीता टाइप नहीं करते हैं!

+0

हां, मुझे 'खाली' के लिए प्रकार पैरामीटर के बारे में पता है; मैं सिर्फ यह दिखाना चाहता था कि कास्टिंग पूरी तरह से तर्क को हल करता है, डिफ़ॉल्ट तर्क के लिए अपेक्षित प्रकार के विपरीत। यह मुझे समझ में नहीं आता है। इसके अलावा मैं इसे 'toSet' से संबंधित प्रश्नों से संबंधित नहीं देखता हूं जिसे आप लिंक करते हैं। –

+0

आप सही हैं, मैंने अपना जवाब पोस्ट करने के बाद मुझे एहसास हुआ कि यह वास्तव में वही मामला नहीं था जैसा मैंने पोस्ट किया था। मुझे थोड़ी अधिक खुदाई करने दें ... हालांकि, अगर आप अपने उदाहरण में 'सेट' के बजाय 'सूची' का उपयोग करते हैं, तो यह काम करता है, मुझे लगता है कि यह संबंधित है। – DaoWen

+0

@ 0__ - मैंने अपने उत्तर में कुछ महत्वपूर्ण संपादन किए हैं, इसलिए आप इसे फिर से पढ़ना चाहेंगे। मुझे अभी भी यकीन नहीं है कि मैंने आपके प्रारंभिक प्रश्न का उत्तर दिया है- मैंने केवल और प्रश्न जोड़े हैं। – DaoWen

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