मैं हैकेल में थोड़ा प्रयोग करने की कोशिश कर रहा हूं, सोच रहा हूं कि आईओ को संसाधित करने के लिए आलस्य का फायदा उठाना संभव है या नहीं। मैं एक ऐसा फ़ंक्शन लिखना चाहता हूं जो स्ट्रिंग (वर्णों की एक सूची) लेता है और एक स्ट्रिंग, आलसी बनाता है। मैं चाहता हूं कि मैं आईओ से पात्रों को आलसी रूप से खिला सकूं, इसलिए प्रत्येक चरित्र को जितनी जल्दी उपलब्ध हो सके संसाधित किया जाएगा, और आउटपुट तैयार किए जाएंगे क्योंकि आवश्यक वर्ण उपलब्ध हो जाएंगे। हालांकि, मुझे पूरा यकीन नहीं है कि मैं आईओ मोनैड के अंदर इनपुट से पात्रों की आलसी सूची कैसे बना सकता हूं।"आलसी आईओ"?
उत्तर
हास्केल में नियमित स्ट्रिंग आईओ आलसी है। तो आपका उदाहरण बस बॉक्स से बाहर काम करना चाहिए।
यहाँ, एक उदाहरण है 'सहभागिता' समारोह, पात्रों में से एक आलसी स्ट्रीम में एक समारोह लागू होता है का उपयोग करते हुए:
interact :: (String -> String) -> IO()
के इनपुट धारा से पत्र 'ई' को फ़िल्टर, lazily करते हैं (यानी रन निरंतर अंतरिक्ष में):
main = interact $ filter (/= 'e')
तुम भी यदि आप चाहें getContents और putStr इस्तेमाल कर सकते हैं। वे सभी आलसी हैं।
यह चल रहा है शब्दकोश से पत्र 'ई' फिल्टर करने के लिए:
$ ghc -O2 --make A.hs
$ ./A +RTS -s < /usr/share/dict/words
...
2 MB total memory in use (0 MB lost due to fragmentation)
...
तो हम देखते हैं कि यह एक निरंतर 2M पदचिह्न में भाग गया।
आप कमांड लाइन पर यह प्रभाव भी देख सकते हैं। खोल/टर्मिनल में डॉन का 'ए' प्रोग्राम चलाएं/जो कुछ भी आपका ओएस उपयोग करता है, और सीधे टेक्स्ट टाइप करें। मान लीजिए कि यह लाइन बफर हो गई है, क्योंकि आप प्रत्येक पंक्ति के बाद एंटर दबाते हैं, आपको तुरंत मुद्रित फ़िल्टर किए गए टेक्स्ट दिखाई देंगे, भले ही प्रोग्राम केवल "कॉल" को 'फ़िल्टर' करने के लिए दिखाई दे। – Nefrubyr
unsafeInterleaveIO :: IO a -> IO a
unsafeInterleaveIO
AllosIO
गणना lazily आस्थगित किया जाना है।IO a
के प्रकार को पारित करते समय,IO
केवल तभी किया जाएगा जबa
का मान मांगे जाए। इसका उपयोग आलसी फ़ाइल पढ़ने को लागू करने के लिए किया जाता है,System.IO.hGetContents
देखें।
उदाहरण के लिए, main = getContents >>= return . map Data.Char.toUpper >>= putStr
आलसी है; जैसे ही आप स्टडीन के पात्रों को खिलाते हैं, आपको स्टडआउट पर अक्षर मिलेंगे।
(यह main = interact $ map Data.Char.toUpper
लेखन, सरगनाओं के जवाब में के रूप में रूप में ही है।)
आलसी आईओ करने का सरलतम विधि सरगनाओं कहते हैं, इस तरह के interact
, readFile
, hGetContents
, और इस तरह के रूप में कार्य करता है; Real World Haskell पुस्तक में इनकी अधिक विस्तृत चर्चा हुई है जो आपको उपयोगी मिल सकती है। अगर स्मृति मुझे सेवा प्रदान करती है, तो ऐसे सभी कार्यों को unsafeInterleaveIO
का उपयोग करके कार्यान्वित किया जाता है जो एपैमेन्ट उल्लेख है, ताकि आप अपने तरीके से अपने तरीके भी बना सकें।
दूसरी ओर, यह ध्यान रखना बुद्धिमान हो सकता है कि unsafeInterleaveIO
टिन पर यह बिल्कुल कहता है: असुरक्षित IO। इसका उपयोग करना - या इसके आधार पर कार्य - breaks purity and referential transparency। मूल्यांकन के दौरान बाहरी दुनिया को प्रभावित करने के लिए स्पष्ट रूप से शुद्ध कार्य (यानी, IO
एक्शन नहीं लौटाता है), उसी तर्क से अलग-अलग परिणाम उत्पन्न करते हैं, और उन सभी अन्य अप्रिय चीजों को अनुमति देता है। व्यावहारिक रूप से, unsafeInterleaveIO
का उपयोग करने के सबसे समझदार तरीके से समस्याएं नहीं आतीं, और साधारण गलतियों का आमतौर पर स्पष्ट और आसानी से निदान की गई बग का परिणाम होता है, लेकिन आपने कुछ अच्छी गारंटी खो दी है।
निश्चित रूप से विकल्प हैं; आप हैकेज पर मिश्रित पुस्तकालयों को पा सकते हैं जो प्रतिबंधित, safer lazy IO या conceptually different approaches प्रदान करते हैं। हालांकि, यह देखते हुए कि व्यावहारिक उपयोग में समस्याएं शायद ही कभी उत्पन्न होती हैं, मुझे लगता है कि ज्यादातर लोग अंतर्निहित, तकनीकी रूप से असुरक्षित कार्यों के साथ रहना चाहते हैं।
कृपया स्पष्ट करें: आप एक ऐसा फ़ंक्शन चाहते हैं जो एक स्ट्रिंग लेता है और "स्ट्रिंग" उत्पन्न करता है --- "उत्पादन" = "रिटर्न", "फ़ाइल संभाल करने के लिए आउटपुट", या क्या? और फिर आप "आईओ से पात्रों को आलसी ढंग से खिलााना चाहते हैं" --- इसका क्या अर्थ है? – dave4420