2009-05-06 15 views
8

को पार्स करने वापस मैं का प्रारूप [(स्ट्रिंग, स्ट्रिंग)] tuples की एक सूची है और मैं एक समारोह की जरूरत है किसी पाठ फ़ाइल में सूची की सामग्री लिखने के लिए, फिर एक और समारोह इस पाठ फ़ाइल को tuples की एक ही सूची के रूप में पढ़ने के लिए। बचत कार्य के लिए मुझे यह मिला है:हास्केल: पाठ फ़ाइलों लेखन और उन्हें मूल स्वरूप

save :: Table -> IO() 
save [] = writeFile "database.txt" "" 
save zs = do { writeFile "database.txt" "" ; sequence_ [appendFile "database.txt" ("("++a++","++b++")\n") | (a,b) <- zs] } 

क्या यह टेक्स्ट फ़ाइल के लिए एक अच्छा प्रारूप होगा? तो मैं उस टेक्स्ट फ़ाइल को कैसे पढ़ सकता हूं और इसे वापस टुपल्स की सूची में कैसे बदल सकता हूं?

उत्तर

12

Prelude में परिभाषित किया जाता है,

type ShowS = String -> String 
class Show a where 
    showsPrec :: Int -> a -> ShowS 
    show :: a -> String 
    showList :: [a] -> ShowS 

type ReadS a = String -> [(a, String)] 
class Read a where 
    readsPrec :: Int -> ReadS a 
    readList :: ReadS [a] 
read :: (Read a) => String -> a 

संक्षेप में, इन हास्केल में मानक "क्रमबद्धता" तरीके हैं। show :: (Show a) => a -> String एक स्ट्रिंग में कुछ भी Show का एक उदाहरण है कि कर सकते हैं और read :: (Read a) => String -> a कुछ भी Read का एक उदाहरण है कि में एक स्ट्रिंग कर देते हैं (या एक अपवाद फेंक) कर सकते हैं।

मानक पुस्तकालय में अधिकांश अंतर्निहित प्रकार और डेटा संरचनाओं में Show और Read उदाहरण परिभाषित किए गए हैं; यदि आप उन लोगों से भागों लिखेंगे, तब अपने प्रकार भी Show और Read उदाहरणों में परिभाषित किया गया है।

type Table = [(String, String)] 

load :: (Read a) => FilePath -> IO a 
load f = do s <- readFile f 
      return (read s) 

save :: (Show a) => a -> FilePath -> IO() 
save x f = writeFile f (show x) 

तो Table एक डेटाप्रकार थे, तो आप उदाहरण के लिए पूछने के लिए है, लेकिन आप अनुरोध कर सकते हैं संकलक उन्हें आपके लिए स्वचालित निकाले जाते हैं।

data Table = Table [(String, String)] 
    deriving (Read, Show) 

कभी-कभी यह संभव नहीं है और आपको अपने स्वयं के उदाहरण परिभाषित करना होगा।

instance Show Table where 
    showsPrec p x = ... 
instance Read Table where 
    readsPrec p x = ... 

लेकिन यह सामान्य नहीं होना चाहिए।

3
अपने वर्तमान समारोह के साथ

आप एक समस्या है जब सूची में स्ट्रिंग से युक्त "," या ")" क्योंकि है कि यह असंभव पता लगाने के लिए जहां एक स्ट्रिंग समाप्त होता है जब आप फिर से डेटा पढ़ने की कोशिश करता है। जब भी वे स्ट्रिंग में दिखाई देते हैं तो आपको इन पात्रों से किसी भी तरह से बचने की आवश्यकता होगी।

यह अपने दम पर यह करने के लिए तो बहुत show और read उपयोग करने के लिए तार के लिए अपने डेटा कन्वर्ट करने के लिए आसान है और वापस:

save :: Table -> IO() 
save zs = writeFile "database.txt" (show zs) 

show विशेष वर्ण बच निकलता है और यकीन है कि डेटा एक स्वरूप है कि यह कर सकते हैं में है बनाता है read द्वारा पार्स किया जाए। डेटा लोड करने के लिए आप एक स्ट्रिंग में फ़ाइल को पढ़ने और read को यह पारित यह अपने वांछित डेटा संरचना को बदलने के लिए होगा।

4

show/read दृष्टिकोण ठीक काम करेगा, मैं इसका भी उपयोग करता हूं, लेकिन केवल छोटे मूल्यों के लिए। बड़े, अधिक जटिल मान read बहुत धीमे हो जाएंगे।

data RevList a = (RevList a) :< a | Nil 
    deriving (Show, Read) 

ghci> read "(((((((((((((((Nil)))))))))))))))" :: RevList Int 

इसके अलावा, read कुछ वैध हास्केल भाव, कि (मेरे उदाहरण में :< की तरह) इन्फ़िक्स कंस्ट्रक्टर्स का उपयोग विशेष रूप से पढ़ने के लिए सक्षम नहीं होगा:

यह काल्पनिक उदाहरण read के खराब प्रदर्शन को दर्शाता है । इस का कारण यह है कि read ऑपरेटरों की स्थिरता के बारे में पता है।यही कारण है कि show $ Nil :< 1 :< 2 :< 3 बहुत प्रतीत होता है अनावश्यक ब्रांड्स उत्पन्न करेगा।

यदि आप बड़े मूल्यों के लिए क्रमबद्धता चाहते हैं, तो मैं Data.Binary जैसी कुछ अन्य लाइब्रेरी का उपयोग करने का सुझाव दूंगा। यह की कमी के कारण मुख्य रूप से show की तुलना में कुछ अधिक जटिल होगा। हालांकि, आपको deriving-सरोगेट्स के समान देने के लिए विभिन्न सामान्य प्रोग्रामिंग समाधान हैं।

निष्कर्ष: मैं show/read समाधान का उपयोग करें जब तक आप उसकी चरम सीमा तक पहुंचने (शायद एक बार आप वास्तविक अनुप्रयोगों का निर्माण शुरू), तो और अधिक विश्वसनीय (लेकिन यह भी अधिक जटिल) डेटा की तरह कुछ को देख शुरू करते हैं, कहते हैं कि चाहते हैं। बाइनरी।


साइड नोट: पार्सर्स और अधिक उन्नत हास्केल सामान में रुचि रखने वालों के लिए; मेरे द्वारा दिए गए उदाहरण पेपर से आए: Haskel Do You Read Me?, एक विकल्प पर, तेजी सेread-जैसी कार्य।

+0

बाइनरी प्राप्त करने के लिए, http://repetae.net/computer/haskell/DrIFT/ दिमाग में आता है। ऐसा कहा जा रहा है, यह निश्चित रूप से संभव है कि इस सरल मामले में रेवलिस्ट के लिए स्मार्ट पढ़ें और दिखाएं, और मैं सहमत हूं कि ओपी को तब तक सरल रहना चाहिए जब तक स्केलेबिलिटी कोई समस्या न हो जाए। – ephemient

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