2009-02-26 4 views
10

में सदस्य प्रकार बनाम पैरामीटर टाइप करें मैं जानना चाहता हूं कि सदस्य प्रकार स्कैला में कैसे काम करते हैं, और मुझे प्रकारों को कैसे जोड़ना चाहिए।स्कैला

एक दृष्टिकोण संबंधित प्रकार को एक प्रकार पैरामीटर बनाना है। इस दृष्टिकोण के फायदे यह है कि मैं इस प्रकार के भिन्नता को निर्धारित कर सकता हूं, और मैं यह सुनिश्चित कर सकता हूं कि उप प्रकार टाइप नहीं बदलता है। नुकसान यह है कि मैं किसी फ़ंक्शन में प्रकार से प्रकार पैरामीटर का अनुमान नहीं लगा सकता।

दूसरा दृष्टिकोण संबंधित प्रकार को दूसरे प्रकार का सदस्य बनाना है, जिसमें समस्या है कि मैं उपप्रकारों के संबंधित प्रकारों पर सीमा निर्धारित नहीं कर सकता हूं और इसलिए, मैं फ़ंक्शन पैरामीटर में प्रकार का उपयोग नहीं कर सकता (जब एक्स: एक्स, एक्स # टी नहीं एक्सटी के साथ किसी भी संबंध में हो सकता है)

एक ठोस उदाहरण होगा:

मैं DFAs के लिए एक विशेषता है (प्रकार पैरामीटर के बिना हो सकता है)

trait DFA[S] { /* S is the type of the symbols in the alphabet */ 
    trait State { def next(x : S); } 
    /* final type Sigma = S */ 
} 

और मैं दौड़ने के लिए एक फ़ंक्शन बनाना चाहता हूं एक इनपुट अनुक्रम में इस DFA, और मैं चाहता हूँ

  • समारोह इनपुट अनुक्रम प्रकार के रूप में कुछ भी <% Seq[alphabet-type-of-the-dfa] रखना चाहिए
  • समारोह फोन करने वाले प्रकार पैरामीटर निर्दिष्ट की जरूरत नहीं है, सभी निष्कर्ष निकाला जा चाहिए
  • मैं था कंक्रीट डीएफए प्रकार के साथ फ़ंक्शन को कॉल करने की तरह (लेकिन यदि कोई समाधान है जहां फ़ंक्शन में डीएफए के लिए टाइप पैरामीटर नहीं होगा, तो यह ठीक है)
  • वर्णमाला प्रकारों को असंवैधानिक (यानी।

    def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = .... 
    

    इस काम करता है: चार के लिए और साथ ही के लिए एक अभी तक अज्ञात उपयोगकर्ता परिभाषित वर्ग एक DFA)

  • भिन्न अक्षर प्रकार के साथ DFAs उपप्रकार

मैं इस कोशिश की नहीं हैं वहाँ होना चाहिए , टाइप एस को छोड़कर यहां अनुमानित नहीं है, इसलिए मुझे प्रत्येक कॉल साइट पर संपूर्ण प्रकार पैरामीटर सूची लिखनी है।

def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]](... same as above 

इस

मैं भी प्रकार पैरामीटर नष्ट कर दिया, एक अमूर्त प्रकार सिग्मा बनाया है और उस प्रकार बंधन की कोशिश की (टाइप करने के लिए डी ??? (यह क्या है?) अमान्य वृत्तीय संदर्भ) काम नहीं किया ठोस कक्षाओं में। runDFA तरह

def runDFA[D <: DFA, SQ <% Seq[D#Sigma]](... same as above 

लगेगा लेकिन यह अनिवार्य रूप से की तरह समस्याओं में चलाता है "प्रकार बेमेल: उम्मीद dfa.Sigma, D#Sigma मिला"

कोई भी विचार? संकेत दिए गए?

संपादित करें:

जवाब के रूप में संकेत मिलता है वहाँ ऐसा करने का कोई आसान तरीका है, किसी के बारे में अधिक विस्तार से बता सकता है क्यों यह असंभव है और क्या होता है परिवर्तित करने की तो यह काम किया?

कारणों से मैं चाहता हूं कि डीडीएफए एक फ्री फ़ंक्शन (एक विधि नहीं) है, मैं अन्य समान कार्य करता हूं जैसे कि automaton minimization, नियमित भाषा संचालन, एनएफए-टू-डीएफए रूपांतरण, भाषा कारक आदि। और सभी यह एक वर्ग के अंदर ओओ डिजाइन के लगभग किसी भी सिद्धांत के खिलाफ है।

+0

वाह, मैंने सोचा कि आपका मतलब यह है: http://www.huygens-fokker.org/scala/ – MusiGenesis

उत्तर

3

सबसे पहले, आप parameterisation वर्ग की जरूरत नहीं है <% Seq [ एस]। सेक [एस] के रूप में विधि पैरामीटर लिखें। यदि एसक्यू <% सेक [एस] तो इसका कोई भी उदाहरण सेक [एस] (जो <% माध्यम है) के लिए पूरी तरह से परिवर्तनीय है, इसलिए जब सेक [एस] के रूप में पारित किया गया तो संकलक स्वचालित रूप से रूपांतरण डालेगा।

इसके अतिरिक्त, जोर्ज ने डी पर टाइप पैरामीटर के बारे में क्या कहा और इसे डीएफए होल्ड पर एक विधि बना दिया। स्केल में आंतरिक कक्षाएं काम करने के तरीके के कारण मैं दृढ़ता से को डीएफए पर runDFA डालकर सलाह देता हूं। जब तक पथ निर्भर टाइपिंग सामान काम नहीं करता है, तब तक कुछ बाहरी वर्ग के आंतरिक वर्गों से निपटना दर्द का थोड़ा सा हो सकता है।

तो अब आप

trait DFA[S]{ 
    ... 

    def runDFA(seq : Seq[S]) = ... 
} 

है और runDFA अचानक नहीं बल्कि के लिए प्रकार पैरामीटर अनुमान लगाने के लिए आसान के सभी है: यह किसी भी जरूरत नहीं है।

3

स्कैला के प्रकार की अनुमान कभी-कभी वांछित होने के लिए बहुत अधिक छोड़ देता है।

क्या कोई कारण है कि आपके डीएफए विशेषता के अंदर विधि क्यों नहीं हो सकती है?

def run[SQ <% Seq[S]](seq: SQ) 

आप डी परम बाद में की जरूरत नहीं है, तो आप भी यह बिना अपने विधि को परिभाषित करने की कोशिश कर सकते हैं:

def runDFA[S, SQ <% Seq[S]](d: DFA[S])(seq: SQ) = ... 
0

पर कुछ उपयोगी जानकारी कैसे दो अलग:

से निराकार guide:

प्रकार पैरामीटर के बिना आप उदाहरण

trait Generic[A] { 
    type Repr 
    def to(value: A): Repr 
    def from(value: Repr): A 
} 

import shapeless.Generic 
def getRepr[A](value: A)(implicit gen: Generic[A]) = 
    gen.to(value) 

यहाँ प्रकार से लौटे, तो निर्भर प्रकार नहीं कर सकता to इनपुट प्रकार A पर निर्भर करता है (क्योंकि आपूर्ति निहित A पर निर्भर करता है):

case class Vec(x: Int, y: Int) 
case class Rect(origin: Vec, size: Vec) 
getRepr(Vec(1, 2)) 
// res1: shapeless.::[Int,shapeless.::[Int,shapeless.HNil]] = 1 :: 2 :: 
    HNil 
getRepr(Rect(Vec(0, 0), Vec(5, 5))) 
// res2: shapeless.::[Vec,shapeless.::[Vec,shapeless.HNil]] = Vec(0,0) 
    :: Vec(5,5) :: HNil 

प्रकार के सदस्यों के बिना इस असंभव होगा:

trait Generic2[A, Repr] 
def getRepr2[A, R](value: A)(implicit generic: Generic2[A, R]): R = 
    ??? 

हम पड़ता था, एक प्रकार पैरामीटर के रूप में getRepr को Repr के वांछित मूल्य पारित करने के लिए effec vely getRepr बेकार बना रही है। Intui ve इस से दूर लेना है कि प्रकार पैरामीटर "इनपुट" और प्रकार के सदस्य उपयोगी हैं "आउटपुट" के रूप में उपयोगी हैं।

कृपया विवरण के लिए आकारहीन guide देखें।

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

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