2011-12-19 17 views
5
एक haskell tutorial बाद

में कार्यान्वित किया जाता, लेखक withFile विधि के निम्नलिखित कार्यान्वयन प्रदान करता है:कैसे withFile Haskell

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a 
withFile' path mode f = do 
    handle <- openFile path mode 
    result <- f handle 
    hClose handle 
    return result 

लेकिन कारण है कि हम एक return में result रैप करने के लिए की जरूरत है? क्या आपूर्ति किए गए फ़ंक्शन f पहले से ही IO वापस नहीं लौटाते हैं, जैसा कि Handle -> IO a द्वारा देखा जा सकता है?

उत्तर

7

आप सही हैं: f पहले से ही एक IO देता है, यदि ऐसा है तो समारोह इस तरह लिखा गया:

withFile' path mode f = do 
    handle <- openFile path mode 
    f handle 

एक वापसी की कोई जरूरत नहीं होगी। समस्या hClose handle के बीच में आता है, तो हम पहला परिणाम स्टोर करने के लिए है:

result <- f handle 

और <- कर IO से छुटकारा मिलता है। तो return इसे वापस रखता है।

+0

ओह डी ओह! पूरी तरह से _sucking_ '<-' ऑपरेटर को याद किया! – drozzy

+1

क्या यह भी परिणाम = एफ संभाल सकता है; एचक्लोस हैंडल; परिणाम 'या फिर मैं फिर से monad समझ में विफल रहा? – delnan

+3

@ डेलनान जो 'डू {हैंडल <- ओपनफाइल मोड पथ होगा; एचक्लोस हैंडल; एफ हैंडल; } ', तो' एफ हैंडल 'शायद एक बंद हैंडल के बारे में शिकायत करेगा। –

3

यह मुश्किल छोटी चीजों में से एक है जिसने मुझे पहली बार हास्केल की कोशिश की जब मुझे भ्रमित कर दिया। आप <- के अर्थ में निर्माण के अर्थ को गलत समझा रहे हैं। result <- f handle का मतलब यह नहीं है "f handle के मान को result" असाइन करें; इसका मतलब है "resultf handle के मोनैडिक मूल्य से 'निकाले गए' मूल्य पर (" निष्कर्षण 'किसी विशेष तरीके से होता है जिसे आप उपयोग कर रहे विशेष मोनाड इंस्टेंस द्वारा परिभाषित किया गया है, इस मामले में आईओ मोनैड)।

अर्थात, और कुछ इकाई typeclass मीटर के लिए, <- बयान दाहिने हाथ की ओर में टाइप m a की अभिव्यक्ति और बाएं हाथ की ओर प्रकार a के एक चर लेता है, और एक मूल्य के लिए चर बांधता है। इस प्रकार आपके विशेष उदाहरण में, result <- f handle के साथ, हमारे पास f result :: IO a, result :: a और return result :: IO a हैं।

पुनश्च कर संकेतन का भी एक विशेष (इस मामले में in कीवर्ड! बिना) let के रूप कि <- करने के लिए एक शुद्ध समकक्ष के रूप में काम करता है। तो अगर आप के रूप में अपने उदाहरण पुनर्लेखन सकता है:,

withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a 
withFile' path mode f = do 
    handle <- openFile path mode 
    let result = f handle 
    hClose handle 
    result 

इस मामले में क्योंकि let एक सीधा काम है, result के प्रकार IO a है।

+1

कूल! मैं '<-' चूसने वाला ऑपरेटर कहता हूं, क्योंकि यह rhs के मान को बेकार करता है :-) – drozzy

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