2012-04-27 14 views
6

यह समस्या एक मॉड्यूल में उभरी है जो मैं लिख रहा हूं, लेकिन मैंने एक मामूली मामला बनाया है जो एक ही व्यवहार को प्रदर्शित करता है।यहां अनुमान लगाने का काम क्यों नहीं करता है?

class Minimal[T](x : T) { 
    def doSomething = x 
} 

object Sugar { 
    type S[T] = { def doSomething : T } 
    def apply[T, X <: S[T]] (x: X) = x.doSomething 
} 

object Error { 
    val a = new Minimal(4) 
    Sugar(a) // error: inferred [Nothing, Minimal[Int]] does not fit the bounds of apply 
    Sugar[Int, Minimal[Int]](a) // works as expected 
} 

समस्या यह है कि संकलक Minimal (Int) के लिए आंतरिक पैरामीटर यह पता लगाने में सफल हुआ है, लेकिन फिर Nothing को T के अन्य घटना है, जो स्पष्ट रूप से apply से मेल नहीं खाता सेट। ये निश्चित रूप से वही T हैं, क्योंकि पहले पैरामीटर को हटाने से दूसरा शिकायत करता है कि टी परिभाषित नहीं है।

क्या कुछ अस्पष्टता है जिसका मतलब है कि संकलक पहले पैरामीटर का अनुमान नहीं लगा सकता है, या यह एक बग है? क्या मैं इस खूबसूरत तरीके से काम कर सकता हूं?

अधिक जानकारी: यह कोड वाक्य रचनात्मक चीनी के प्रयास का एक साधारण उदाहरण है। मूल कोड |(a)| बनाने का प्रयास करता है जिसका मतलब a का मॉड्यूलस है, जहां एक वेक्टर है। स्पष्ट रूप से |(a)||[Float,Vector3[Float]](a)| लिखने से बेहतर है, लेकिन दुर्भाग्य से मैं इसे आसान बनाने के लिए unary_| का उपयोग नहीं कर सकता।

वास्तविक त्रुटि:

inferred type arguments [Nothing,Minimal[Int]] do not conform to method apply's type parameter bounds [T,X <: Sugar.S[T]]

उत्तर

9

यह स्कैला कंपाइलर बग नहीं है, लेकिन यह निश्चित रूप से स्कैला के प्रकार की अनुमान की सीमा है। X के लिए हल करने से पहले संकलक X, S[T] पर बाध्य निर्धारित करना चाहता है, लेकिन बाध्य अब तक असंबंधित प्रकार परिवर्तनीय T का उल्लेख करता है जो इसलिए Nothing पर ठीक हो जाता है और वहां से प्राप्त होता है। यह T पर फिर से समीक्षा नहीं करता है X पूरी तरह से हल हो गया है ... वर्तमान में टाइप करें इस तरह के मामले में बाएं से दाएं हमेशा अनुमान लगाते हैं।

अपने उदाहरण सही रूप में आपके वास्तविक स्थिति का प्रतिनिधित्व करता है तो उन्हें आसानी से ठीक,

def apply[T](x : S[T]) = x.doSomething 

यहाँ T अनुमान लगाया जा होगा ऐसी है कि MinimalS[T] को सीधे बजाय एक मध्यस्थ घिरे प्रकार चर के माध्यम से अनुरूप है।

अद्यतन

जोशुआ की समाधान भी प्रकार T का निष्कर्ष निकालते की समस्या से बचा जाता है, लेकिन एक पूरी तरह से अलग तरीके से।

def apply[T, X <% S[T]](x : X) = x.doSomething 

को desugars,

def apply[T, X](x : X)(implicit conv : X => S[T]) = x.doSomething 

प्रकार चर T और X अब स्वतंत्र रूप से करने के लिए हल किया जा सकता (क्योंकि T नहीं रह गया है X के लिए बाध्य में बताया गया है)।इसका मतलब है कि X को तत्काल Minimal के रूप में अनुमानित किया गया है, और T को X => S[T] के मूल्य के लिए अंतर्निहित खोज के हिस्से के रूप में हल किया गया है ताकि निहित तर्क conv को पूरा किया जा सके। conformsscala.Predef इस फ़ॉर्म के मूल्यों का निर्माण करता है, और संदर्भ में यह गारंटी होगी कि Minimal, T के तर्क को इंट के रूप में अनुमानित किया जाएगा। आप इसे स्कैला में काम पर functional dependencies के उदाहरण के रूप में देख सकते हैं।

+0

हां, यह समाधान मेरे मामले में ठीक काम करता है। यह यहोशू के समाधान से भी साफ है (क्षमा करें यहोशू!)। क्या आप समझा सकते हैं कि यहोशू का समाधान क्यों काम करता है? – Dylan

+0

उत्तर देने के लिए उत्तर दिया गया कि यहोशू का समाधान भी क्यों काम करता है। –

4

संरचनात्मक प्रकार पर सीमा के साथ कुछ weirdness है, एक दृश्य के एस [टी] के बजाय पर बाध्य उपयोग करके देखें।

def apply[T, X <% S[T]] (x: X) = x.doSomething ठीक काम करता है।

+1

बढ़िया, यह काम करता है, लेकिन निश्चित रूप से दृष्टिकोण के बीच कोई अंतर नहीं होना चाहिए? इस मामले में एक विचार लेना सिर्फ सुपरक्लास को कास्टिंग कर रहा है, है ना? क्या इसका मतलब यह है कि यह फिक्स कंपाइलर में एक बग के लिए सिर्फ एक कामकाज है? – Dylan

+0

आह, अब मैं देखता हूं, 'एस' एक सुपरक्लास नहीं है - यह सिर्फ एक दृश्य है (एक अर्थ में)। इसलिए अधिकांश मामलों में जरूरी नहीं होने के बावजूद एक दृश्य बाध्य अधिक उपयुक्त है। – Dylan

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

  • कोई संबंधित समस्या नहीं^_^