2011-07-08 10 views
7

मैं फ़ंक्शन लिखना चाहता हूं और स्ट्रिंग को परिणाम देना चाहता हूं।हास्केल आईओ (स्ट्रिंग) और स्ट्रिंग

read' :: FilePath -> String 

मैं का उपयोग करें::

मैं समारोह चाहते

:t readFile 
readFile :: FilePath -> IO String 

मैं:

read' :: IO() 
read' = do 
    str <- readFile "/home/shk/workspace/src/test.txt" 
    putStrLn str 

मैं str पूछना चाहता हूँ स्ट्रिंग है या नहीं?

हम जानते हैं कि:

:t putStrLn 
putStrLn :: String -> IO() 

तो फिर मैं नहीं कर सकता:

read' :: String 
read' = do 
    str <- readFile "/home/shk/workspace/lxmpp/src/test.txt" 
    str 

मैं त्रुटि मिलती है कि:

Couldn't match expected type `[t0]' with actual type `IO String' 
    In the return type of a call of `readFile' 
    In a stmt of a 'do' expression: 
     str <- readFile "/home/shk/workspace/lxmpp/src/test.txt" 
    In the expression: 
     do { str <- readFile "/home/shk/workspace/src/test.txt"; 
      str } 

धन्यवाद।

+4

पढ़ाई में पढ़ा गया फ़िल का तात्पर्य है कि आप आईओ मोनैड में हैं, और आईओ मोनड से बच नहीं सकते! – is7s

+0

@ is7s जब तक आप 'unsafePerformIO' का उपयोग नहीं करते हैं! – alternative

+10

असुरक्षित पैराफॉर्मियो का पहला नियम है कि आप किसी को भी असुरक्षित जानकारी के बारे में नहीं बताते हैं! –

उत्तर

6

मुझे लगता है कि कोई भी इस बहुत महत्वपूर्ण सवाल है, अभी तक उत्तर है:

मैं str पूछना चाहता हूँ स्ट्रिंग या नहीं है?

मैं कोशिश करूंगा।

परिवर्तनीय str का प्रकार String है, हां। हालांकि, इस चर का दायरा बहुत सीमित है। मुझे लगता है कि do-अंकन desugaring समझ के लिए आवश्यक है:

read' = readFile "/home/shk/workspace/src/test.txt" >>= (\str -> putStrLn str) 

मैं यहाँ लगता है कि यह अधिक स्पष्ट हो जाता है क्यों str काफी अच्छा नहीं है। यह पर भेजे गए फ़ंक्शन के तर्क है। इसका मूल्य केवल तभी उपलब्ध हो जाता है जब कोई आपके फ़ंक्शन को कॉल करता है, जो तब होता है जब IO क्रिया को निष्पादित किया जा रहा है।

इसके अलावा, read' :: IO() का प्रकार putStrLn str द्वारा इतना निर्धारित नहीं है, बल्कि ऑपरेटर >>= के रिटर्न प्रकार द्वारा निर्धारित किया गया है। यह पर एक नज़र (IO इकाई के लिए विशेष) है:

(>>=) :: IO a -> (a -> IO b) -> IO b 

आप देख सकते हैं कि परिणाम हमेशा एक IO b कार्रवाई है, इसलिए बदलने के लिए तर्क से किसी की मदद नहीं करेगा कोशिश कर रहा।

यदि आप समझना चाहते हैं कि यह तरीका किस प्रकार है, तो आप कुछ मोनैड ट्यूटोरियल पढ़ सकते हैं। इसके पीछे अंतर्ज्ञान यह है कि आप कोई कार्रवाई किए बिना कोई कार्रवाई नहीं कर सकते हैं।

और सवाल के व्यावहारिक पक्ष पर, के बजाय जो मतलब नहीं है क्योंकि extractValue संभव नहीं है, use (extractValue inputAction) करने के लिए कोशिश कर के, कुछ कार्रवाई द्वारा दिए गए मान का उपयोग inputAction >>= use कोशिश करता है, तो करने के लिए अपने use मैं शामिल है/हे , या fmap use inputAction यदि यह नहीं करता है।

4

read' में return str का उपयोग करना चाहिए यदि आप इसे () के बजाय str वापस करना चाहते हैं। read' के प्रकार से आप IO को पट्टी नहीं कर सकते हैं, क्योंकि यह शुद्ध कार्य नहीं है। हास्केल में इनपुट/आउटपुट के तरीके पर बेहतर पकड़ पाने के लिए मैं आपको to read a tutorial की सलाह देता हूं।

+3

हालांकि यह सही है, ध्यान दें कि '<-' के साथ बाध्यकारी में कोई बिंदु नहीं है, बस इसे तुरंत 'वापसी' करने के लिए। आप बस 'read' = readFile "/path/to/test.txt" लिख सकते हैं। यह [दूसरा मोनाद कानून] है (http://www.haskell.org/haskellwiki/Monad_Laws)। – hammar

1

अधिक विस्तृत कारण के रूप में: यह अशुद्धता की अनुमति देता है।

आप शुद्ध संचालन के दौरान पूरी तरह से आईओ नहीं कर सकते हैं, या यह पूरी तरह से पारदर्शी पारदर्शिता तोड़ देगा। तकनीकी रूप से आप unsafePerformIO का उपयोग कर सकते हैं लेकिन यह इस मामले में संदर्भित पारदर्शिता तोड़ देगा - आपको केवल इसका उपयोग करना चाहिए यदि आप गारंटी दे सकते हैं कि परिणाम हमेशा है।

+1

क्या परिणाम की गारंटी शुद्धता का दावा करने के लिए पर्याप्त है? मेरा मतलब है, 'unsafePerformIO (putStrLn "हैलो!")' शुद्ध कहा जा सकता है? – Rotsor

+1

@Rotsor: यह न भूलें कि इसे थ्रेड-सुरक्षित भी होना चाहिए। गारंटी की शुद्धता मैन्युअल रूप से मुश्किल है! –

+0

@camccann मुझे यकीन नहीं है कि आपकी टिप्पणी की व्याख्या कैसे करें। क्या आप मोनैडिक उपयोगकर्ता परिभाषित शुद्धता की धारणा को विस्तारित कर रहे हैं, या इसे प्राप्त करने की व्यावहारिक कठिनाइयों का सुझाव दे रहे हैं? यदि विस्तारित नहीं किया गया है, तो यह कह सकता है, 'सुरक्षितPERFORIO = unsafePerformIO :: IO() ->()', है ना? कौन सा बुरा है ... या नहीं? – Rotsor

10

बस थोड़ी अधिक quibble करने के लिए, जबकि अन्य उत्तरों पूरी तरह से सही हैं, मैं कुछ पर जोर देना चाहता हूं: IO String प्रकार के साथ कुछ सिर्फ एक स्ट्रिंग नहीं है कि टाइप सिस्टम आपको सीधे नहीं जाने देगा। यह एक गणना है कि आपके लिए स्ट्रिंग प्राप्त करने के लिए I/O निष्पादित करता हैreadFile को फ़ाइल पथ पर लागू करने से String किसी मांस ग्राइंडर के बगल में एक स्टेक डालने से अधिक मूल्य वापस नहीं आता है, जो उन्हें एक हैमबर्गर में बदल देता है।

आप इस तरह कुछ कोड है जब:

foo = do let getStr = readFile "input.txt" 
     s1 <- getStr 
     s2 <- getStr 
     -- etc. 

आप "दो बार getStr से बाहर स्ट्रिंग ले रही है" कर रहे हैं इसका मतलब यह नहीं है। इसका मतलब है कि आप दो बार गणना कर रहे हैं और दोनों के बीच आसानी से अलग-अलग परिणाम प्राप्त कर सकते हैं।

+0

जादू हैम्बर्गर के बारे में अच्छी बात यह है कि आप साइड इफेक्ट्स के बारे में चिंता किए बिना उन्हें खा सकते हैं! – pat

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