2010-11-13 9 views
5

उपयोग करने के लिए मैं कुछ डेटा जो अपने आप में उपयोग करने के लिए डेटा प्रकार निर्दिष्ट पढ़ना चाहते हैं डेटा प्रकार निर्दिष्ट करता है।पढ़ना और प्रतिनिधित्व करने इनपुट जो

उदाहरण के लिए, वहाँ मान इस तरह के उपयोगकर्ता इनपुट हो सकता है:

integer pair 1 2 
integer triple 1 2 3 
real pair 1 2 
real triple 1 2 3 

और वहाँ एक डेटा यह प्रतिनिधित्व करने के लिए प्रकार है: जहां की अनुमति दी मूल्य प्रकार के हैं करने के लिए है

data (MValue a) => T a = TP (Pair a) | TT (Triple a) 
    deriving (Show, Eq) 

data Pair a = Pair a a deriving (Show, Eq) 
data Triple a = Triple a a a deriving (Show, Eq) 

MValue वर्ग:

class (Num a, Read a) => MValue a where 
    typename :: a -> String 
    readval :: [String] -> Maybe a 

instance MValue Int where 
    typename _ = "integer" 
    readval [s] = maybeRead s 
    readval _ = Nothing 

instance MValue Double where 
    typename _ = "real" 
    readval [s] = maybeRead s 
    readval _ = Nothing 

maybeRead s = 
    case reads s of 
    [(x,_)] -> Just x 
    _  -> Nothing 

मैं आसानी से पाठकोंके लिए लिख सकते हैंऔर Triple रों:

readPair (w1:w2:[]) = Pair <$> maybeRead w1 <*> maybeRead w2 
readTriple (w1:w2:w3:[]) = Triple <$> maybeRead w1 <*> maybeRead w2 <*> maybeRead w3 

समस्या कैसे मैं पूरी T a प्रकार के लिए एक बहुरूपी पाठक लिख सकता हूँ है:

मैं चाहता हूँ:

  1. प्रकार a कॉलर द्वारा चुना जाता है।
  2. readTNothing उत्पादन करना चाहिए अगर उपयोगकर्ता के इनपुट a साथ असंगत है।
  3. readTJust (T a) उत्पादन करना चाहिए अगर इनपुट मान्य है।
  4. नंबर या इनपुट के आधार पर दोगुना हो जाता है के रूप में पूर्णांक के रूप में पढ़ा जाना चाहिए।

एक अनुभवहीन कार्यान्वयन

readT :: (MValue a, Read a) => String -> Maybe (T a) 
readT s = 
    case words s of 
    (tp:frm:rest) -> 
     if tp /= typename (undefined :: a) 
      then Nothing 
      else case frm of 
      "pair" -> TP <$> readPair rest 
      "triple" -> TT <$> readTriple rest 
      _ -> Nothing 
    _ -> Nothing 

लाइन if tp /= typename (undefined :: a) में एक त्रुटि देता है:

rd.hs:45:17: 
    Ambiguous type variable `a' in the constraint: 
     `MValue a' arising from a use of `typename' at rd.hs:45:17-41 
    Probable fix: add a type signature that fixes these type variable(s) 
Failed, modules loaded: none. 

त्रुटि दूर हो जाता है तो मैं इस चेक को दूर है, लेकिन मैं कैसे सत्यापित कर सकते हैं, तो उपयोगकर्ता इनपुट कॉलर द्वारा चुने गए डेटा प्रकार के साथ संगत है? एक समाधान अलग readTInt और readTDouble के लिए हो सकता है, लेकिन मैं एक ही readT polymorphically उसी तरह read करता है के रूप में काम करना चाहते हैं।

उत्तर

5

समस्या यह है कि undefined :: a में a ही areadT के हस्ताक्षर में लोगों के रूप में नहीं है। जीएचसी में एक भाषा विस्तार उपलब्ध है जो इसे सक्षम बनाता है, जिसे "स्कोप्ड टाइप टाइपरीबल्स" कहा जाता है। एक अधिक पोर्टेबल ठीक उदाहरण के लिए, थोड़ा अतिरिक्त कोड स्पष्ट प्रकार एक साथ टाई लागू करने के लिए होगा:

readT :: (MValue a, Read a) => String -> Maybe (T a) 
readT s = result 
    where 
    result = 
     case words s of 
     (tp:frm:rest) -> 
      if tp /= typename ((const :: a -> Maybe (T a) -> a) undefined result) 
       then Nothing 
       else case frm of 
       "pair" -> TP <$> readPair rest 
       "triple" -> TT <$> readTriple rest 
       _ -> Nothing 
     _ -> Nothing 

यह आपके कोड का एक बहुत ही त्वरित और गंदी संशोधन है, और मैं परिवर्तन किया जा सकता है कर रहा हूँ अधिक सुंदरता, लेकिन यह काम करना चाहिए।

+0

धन्यवाद। यह काम। 'परिणाम' के साथ चाल अपरिभाषित 'तर्क (टी ए) -> ए' के लिए तर्क के रूप में अप्रत्याशित है। – sastanin

+1

असल में, 'परिणाम' और 'अपरिभाषित' दोनों कॉन्स्ट :: ए -> हो सकता है (टी ए) -> ए ', जो कि उनके प्रकार को 'const' पर स्पष्ट प्रकार हस्ताक्षर द्वारा दिए गए तरीके से संबंधित करने के लिए मजबूर करता है '। लेकिन हाँ, '(अपरिभाषित :: शायद (टी ए) -> ए) परिणाम 'भी काम करेगा। – mokus

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