2008-10-18 7 views
11

मैं वर्तमान में हास्केल के साथ प्रोजेक्ट पर काम कर रहा हूं, और मुझे कुछ परेशानी मिली है। मुझे "dictionary.txt" फ़ाइल में प्रत्येक पंक्ति को एक सूची में पढ़ना और डालना है, लेकिन मुझे ऐसा नहीं लगता है। ठीक से काम करता है एक "putStrLn inpStr" के साथ: "सूची inpStr", सभी लाइनों को प्रदर्शित करनेहास्केल: फ़ाइल से प्रत्येक पंक्ति को एक सूची में सम्मिलित करना

main = do 
    let list = [] 
    loadNums "dictionary.txt" list 

loadNums location list = do 
    inh <- openFile location ReadMode 
    mainloop inh list 
    hClose inh 

mainloop inh list = do 
    ineof <- hIsEOF inh 
    if ineof 
     then return() 
     else do 
      inpStr <- hGetLine inh 
      inpStr:list 
      mainloop inh list 

यह हर लाइन (मैं जानता हूँ कि यह हर पंक्ति प्राप्त करता है, की जगह के बाद से प्राप्त करने के लिए माना जाता है: मैं इस कोड मिल गया है), और यह एक सूची में डालने, लेकिन मैं निम्नलिखित त्रुटि मिलती है:

Couldn't match expected type `IO' against inferred type `[]' 

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

अग्रिम धन्यवाद!

उत्तर

14

लाइन में जहां त्रुटि होती है, हास्केल "आईओ ए" की अपेक्षा कर रहा है, लेकिन आप इसे एक [] दे रहे हैं। आईओ मोनैड पर एक डॉक ब्लॉक पर चीजों को सरल बनाना, प्रत्येक पंक्ति या तो है:

  • कुछ जो "आईओ ए" प्रकार का मान देता है; इसके अंदर "ए" प्रकार का मान त्याग दिया जाता है (इसलिए "ए" अक्सर "()")
  • ए < - अभिव्यक्ति, जो एक ही चीज़ करता है लेकिन "ए" प्रकार के मान को छोड़ने के बजाय यह < के बाईं ओर नाम देता है -
  • एक लेट है, जो एक मूल्य

से अधिक एक नाम देने के कुछ नहीं करता है कि ब्लॉक में, "hGetLine INH" रिटर्न एक "आईओ स्ट्रिंग" , और इसके अंदर स्ट्रिंग निकाली जाती है और नाम inpStr दिया जाता है। अगली पंक्ति, चूंकि यह न तो एक है या < -, एक प्रकार "आईओ ए" होना चाहिए, जो यह नहीं करता है (इस प्रकार संकलक त्रुटि उत्पन्न करता है)।

let list' = inpStr:list 

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

"सूची" के बजाय "सूची" का उपयोग करने के लिए निम्न पंक्ति बदलें (इस प्रकार इसे नई सूची पास कर रहा है)। वह लाइन कॉल (रिकर्सिवली) मेनलोप कहती है, जो एक और लाइन पढ़ेगी, खुद को कॉल करेगी, और इसी तरह। पूरी फाइल पढ़ने के बाद, यह "आईओ()" प्रकार के साथ कुछ वापस कर देगा। यह "आईओ()" लोड नम्स पर डू ब्लॉक पर वापस कर दिया जाएगा। बधाई हो, आपने फ़ाइल से पढ़ने वाली लाइनों के साथ एक सूची बनाई है, रिवर्स ऑर्डर में (क्योंकि आप सूची के प्रमुख में शामिल थे), और उसके बाद कुछ भी नहीं किया।

यदि आप इसे कुछ करना चाहते हैं, तो "वापसी()" को "वापसी सूची" में बदलें; रिटर्न "आईओ [स्ट्रिंग]" प्रकार का एक मूल्य उत्पन्न करेगा, इसके भीतर की सूची के साथ (वापसी मूल्य को encapsulating से अधिक कुछ नहीं करता है), जिसे आप < - वाक्यविन्यास के साथ loadNums पर निकाल सकते हैं।

बाकी को पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है।

15

जब तक यह होमवर्क या कुछ के लिए नहीं है, तो इतने सारे प्रयासों का उपयोग करने का कोई कारण नहीं है। पुन: उपयोग आलसी है!

getLines = liftM lines . readFile 

main = do 
    list <- getLines "dictionary.txt" 
    mapM_ putStrLn list 

लेकिन जैसा कि आप अभी भी हास्केल सीख रहे हैं, यह समझना आपके लिए महत्वपूर्ण है कि सीज़रबी ने क्या लिखा है।

+0

किसी ऐसे व्यक्ति को चीजों को समझाते समय जो हास्केल सीख रहा है, मैं व्यर्थ शैली का उपयोग (या यहां तक ​​कि दिखा रहा) से बचाना चाहता हूं। उन्हें पढ़ने के लिए नहीं चाहते ;-) – CesarB

+7

+1 'readFile' का उल्लेख करने के लिए +1। ओपन फाइल/रीड लाइन/ईओएफ/क्लोज़ फाइल का पता लगाने की अनिवार्य मानसिकता से बाहर निकलना बहुत उपयोगी है, और 'readFile', 'getContents' और' interact' जैसे कार्यों को आपके लिए गड़बड़ करने दें। – Nefrubyr

+0

"mapM_" का क्या अर्थ है? मुझे पता है कि "mapM" मोनैड के लिए एक फ़ंक्शन को मानचित्र करता है .. लेकिन अंडरस्कोर वाला वाला एक? – drozzy

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