2010-06-26 9 views
11

मैं मजेदार के लिए स्कैला 2.8 के साथ गड़बड़ कर रहा था और pimp को परिभाषित करने की कोशिश कर रहा था जो एक मज़ेदार से दूसरे में कनवर्ट करने की अनुमति देने वाले रचनाकारों को टाइप करने के लिए "as" विधि जोड़ता है (कृपया इस तथ्य को नजरअंदाज करें कि मैं जरूरी नहीं कि यहां मज़दूरों से निपटना पड़े)। तो उदाहरण के लिए, आप इसे इस तरह इस्तेमाल कर सकते हैं:"पैरामीटरयुक्त प्रकार से अस्तित्व में सार नहीं हो सकता है ..."

val array:Array[T] 
val list:List[T] = array.as[List] 
तो यहाँ

है मैं करने की कोशिश की क्या:

object Test { 
    abstract class NatTrans[F[_], G[_]] { 
     def convert[T](f:F[T]):G[T] 
    } 

    implicit def array2List:NatTrans[Array, List] = new NatTrans[Array, List] { 
     def convert[T](a:Array[T]) = a.toList 
    } 

    // this next part gets flagged with an error 
    implicit def naturalTransformations[T, F[_]](f:F[T]) = new { 
     def as[G[_]](implicit n:NatTrans[F, G]) = n convert f 
    } 
} 

तथापि naturalTransformations की परिभाषा त्रुटि "existentially सार नहीं कर सकते हैं के साथ चिह्नित कर देने पर पैरामीटरकृत प्रकार जी [टी] " पर। इसे ठीक करने के लिए, मैं एक अतिरिक्त वर्ग Transformable के साथ naturalTransformations पुनर्लेखन कर सकते हैं ताकि तरह:

class Transformable[T, F[_]](f:F[T]) { 
    def as[G[_]](implicit n:NatTrans[F, G]) = n convert f 
} 

implicit def naturalTransformations[T, F[_]](f:F[T]) = new Transformable[T, F](f) 

और यह काम करने के लिए प्रकट होता है। लेकिन ऐसा लगता है कि मेरा पहला प्रयास समकक्ष होना चाहिए था, इसलिए मुझे उत्सुकता है कि यह क्यों विफल रहा और त्रुटि संदेश का क्या अर्थ है।

+1

मुझे त्रुटि देखने के लिए उपयोग किया जाता है "संरचनात्मक परिष्करण में पैरामीटर प्रकार समान परिस्थितियों में परिभाषित किए गए एक सार प्रकार को संदर्भित नहीं कर सकता है। यह प्रतिबंध प्रतिबिंब, आईआईआरसी के साथ जेवीएम पर संरचनात्मक प्रकार लागू किए जाने के तरीके से संबंधित है। http://stackoverflow.com/questions/2685804/scala-parameter-type-in-structural-refinement-may-not-refer-to-an-abstract-type – retronym

उत्तर

10

मेरे कूबड़ होगा कि इस वजह से कल्पना में निम्नलिखित बयानों, § 6.11, ब्लॉक की वजह से है:

एक स्थानीय रूप से परिभाषित प्रकार परिभाषा प्रकार टी = टी अस्तित्व खंड प्रकार टी से बाध्य है >: टी <: टी। टी में टाइप पैरामीटर होने पर यह एक त्रुटि है।

और एक संरचनात्मक उदाहरण निर्माण अभिव्यक्ति एक ब्लॉक करने के लिए मूल्यांकन किया जाता है, तो


new {def greet{println("hello")}} 

(§ 6,10 की के अनुसार


{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X } 
तो

के लिए एक आशुलिपि यह एक ब्लॉक अभिव्यक्ति का आकलन करती है कल्पना), उपर्युक्त प्रतिबंध के साथ। हालांकि, यह प्रतिबंध क्यों है, मुझे नहीं पता। फेंकने वाली त्रुटि को this location पर टायर्स क्लास में पाया जा सकता है, जो यह पुष्टि करता है कि यह प्रतिबंध आपको दिखाई देने वाली त्रुटि का कारण है। इस व्यापकता मामले के खिलाफ एक सादगी की तरह लगता है


scala> class N[M[_]] 
defined class N 

scala> class Q { def as[M[_]](n:N[M]) = null} 
defined class Q 

scala> new { def as[M[_]](n:N[M]) = null}  
:7: error: can't existentially abstract over parameterized type M 
     new { def as[M[_]](n:N[M]) = null} 

0

मेरे लिए: आप उल्लेख किया है, एक कक्षा में समारोह एन्कोडिंग ब्लॉक अभिव्यक्ति प्रतिबंध को हटा वहाँ एक नए प्रकार हर बार एक ब्लॉक कैप्चरिंग बनाई गई है उत्पन्न चर हो सकता है अस्तित्व के प्रकार के साथ तत्काल कुछ प्रकार का कन्स्ट्रक्टर, लेकिन इससे त्रुटि निदान को समझना मुश्किल हो जाएगा।

यह भी ध्यान रखें कि कक्षा होने से प्रतिबिंब द्वारा () विधि के रूप में कॉल करने के बजाए कॉल को तेजी से INVOKEVIRTUAL में बदल दिया जाता है।

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