2012-04-02 15 views
7

का एक विशेष रूप पारदर्शी रूप से कार्यान्वित करना मूलभूत विचार यह है कि मेरे पास कई प्रकार के फ़ंक्शन हैं जो किसी विशेष वर्ग से किसी भी प्रकार पर काम करते हैं, लेकिन रनटाइम पर प्रोग्राम को कॉन्फ़िगरेशन फ़ाइल पढ़नी होती है और एक तत्व निकालना होता है कक्षा में प्रकार के।गतिशील टाइपिंग

उदाहरण के लिए, मेरे पास 'गुणांक' वर्ग, इसके विभिन्न उदाहरण हैं, और उस वर्ग के प्रकारों पर पॉलिमॉर्फिक के विभिन्न प्रकार के कार्य हैं; रनटाइम पर उस वर्ग का एक विशेष प्रकार निर्धारित किया जाना है, और चारों ओर पारित किया जाना है।


मुझे यकीन है कि इसे ठीक से कैसे संबोधित किया जाए; मैं 'यौगिक' प्रकार बनाने की कोशिश की, की तरह कुछ कर रही है:

data CompoundCoeff = CompoundInt Int | CompoundDouble Double | ... 

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

Coefficient a => a -> (stuff not involving a anymore) 

लेकिन दुर्भाग्य से यह मामला नहीं है।

एक और मुद्दा मैं में भाग गया, कि मैं प्रकार परिवारों का उपयोग कर रहा है, और जैसे

class (Monoid (ColourData c), Coordinate (InputData c)) => ColourScheme c where 
    type ColourData c :: * 
    type InputData c :: * 
    colouriseData  :: c -> (ColourData c) -> AlphaColour Double 
    processInput  :: c -> InputData c -> ColourData c 

कुछ मैं यौगिक ColourData डेटाप्रकार किसी प्रकार का उपयोग करने के लिए है, तो यह सफाई से पूरा नहीं होता है, की तरह है पिछला वाला; विशेष रूप से मैं अब गारंटी नहीं दे सकता कि डेटा स्ट्रीम एक स्थिर प्रकार प्रदान करता है (और एक कंपाउंड प्रकार के अलग-अलग 'उपप्रकार' नहीं), और (अन्य चीजों के साथ) एक बोगस मोनॉयड उदाहरण बनाना होगा यदि मैंने एक किया कंपाउंड ColourData प्रकार।

मैंने डेटा में भी देखा है। गतिशील, लेकिन फिर से मैं नहीं देख सकता कि यह मुद्दों को सही तरीके से कैसे संबोधित करेगा; वही समस्याएं दिखाई देने लगती हैं (अच्छी तरह से, थोड़ा और भी बदतर, यह देखते हुए कि केवल एक 'सामान्य' गतिशील प्रकार है जैसा कि मैं इसे समझता हूं)।


प्रश्न: कैसे मैं उन डेटा प्रकार को शामिल सभी कार्यों को फिर से लिखने के बिना विशेष कक्षाओं के अधीनस्थ गतिशील डेटाटाइप्स लागू कर सकते हैं? अगर मुझे किसी प्रकार की सुरक्षा बलिदान नहीं करना पड़ेगा तो यह सबसे अच्छा होगा, लेकिन मैं बहुत आशावादी नहीं हूं।
प्रोग्राम रनटाइम पर एक कॉन्फ़िगरेशन फ़ाइल को पढ़ना है, और सभी आवश्यक कार्यों, प्रासंगिक वर्ग पर बहुलक, लागू किया जाना है। GADTs है, जो अधिक पठनीय हो सकता है के साथ

{-# LANGUAGE ExistentialTypes #-} 
data SomeFoo = forall a . Foo a => SomeFoo a 

instance Foo SomeFoo where 
    -- all operations just unwrap the SomeFoo straightforwardly 

या,:

उत्तर

7

एक वस्तु की गारंटी देता है कि है कि यह typeclass Foo का एक उदाहरण है, लेकिन कोई अतिरिक्त गारंटी नहीं देता है प्रदान करने के लिए परंपरागत तरीके से, तो तरह है। ..

data SomeFoo where 
    SomeFoo :: Foo a => a -> SomeFoo 
6

एक प्रस्ताव एक भी उच्च-स्तरीय समारोह है कि सभी परिष्करण करता है लिखने के लिए छू लेती होगा एक बार आप एक प्रकार चुना है:

topLevel :: SomeTypeClass a => a -> IO() 

आपका कार्यक्रम तो कुछ इस तरह लिखा जा सकता है:

main = do 
    config <- readConfig 
    case config of 
     UseDouble n -> topLevel n 
     UseSymbolic x -> topLevel x 
     UseWidgetFrobnosticator wf -> topLevel wf 
संबंधित मुद्दे