2012-03-22 17 views
10

मैंने सोचा था कि सैद्धांतिक हैकेल की प्रकार प्रणाली शुद्ध लोगों से अशुद्ध कार्यों (यानी f :: a -> IO b) को कॉल करने से मना कर देगी, लेकिन आज मुझे एहसास हुआ कि उन्हें return के साथ बुलाकर वे ठीक से संकलित हैं। उदाहरण में:शुद्ध कार्यों के भीतर आईओ कार्यों का क्या अर्थ है?

h :: Maybe() 
h = do 
    return $ putStrLn "???" 
    return() 

अब, शायद में h काम करता है इकाई है, लेकिन यह एक शुद्ध समारोह फिर भी है। संकलन और इसे चलाने से बस Just() लौटाता है जैसा कि कोई उम्मीद करेगा, बिना किसी I/O के। मुझे लगता है कि हैकेल की आलस्य चीजों को एक साथ रखती है (यानी putStrLn का रिटर्न वैल्यू उपयोग नहीं किया जाता है - और चूंकि इसके मूल्य निर्माता छिपाए नहीं जा सकते हैं और मैं इसके खिलाफ पैटर्न मिलान नहीं कर सकता), लेकिन यह कोड कानूनी क्यों है? क्या कोई अन्य कारण है जो इसे अनुमति देता है?

बोनस के रूप में, संबंधित प्रश्न: सामान्य रूप से, क्या किसी अन्य के भीतर से एक मोनैड के कार्यों के निष्पादन पर रोक लगाना संभव है? कैसे?

उत्तर

19

आईओ क्रियाएं किसी अन्य की तरह प्रथम श्रेणी के मान हैं; यही कारण है कि हास्केल का आईओ इतना अभिव्यक्तिपूर्ण बनाता है, जिससे आप स्क्रैच से उच्च-आदेश नियंत्रण संरचनाओं (जैसे mapM_) का निर्माण कर सकते हैं। आलस्य यहां प्रासंगिक नहीं है, यह है कि आप वास्तव में कार्रवाई नहीं कर रहे हैं कार्रवाई। आप केवल Just (putStrLn "???") मान बना रहे हैं, फिर इसे फेंक रहे हैं।

putStrLn "???"मौजूदा स्क्रीन पर एक पंक्ति मुद्रित नहीं होती है। अपने आप से, putStrLn "???" कुछ आईओओ के विवरण विवरण है जो स्क्रीन पर एक पंक्ति मुद्रित करने के कारण किया जा सकता है। ऐसा होने वाला एकमात्र निष्पादन main निष्पादित कर रहा है, जिसे आपने अन्य आईओ क्रियाओं से बनाया है, या जो भी कार्य आप जीएचसीआई में टाइप करते हैं। अधिक जानकारी के लिए, introduction to IO देखें।

दरअसल, यह पूरी तरह से कल्पना की जा सकती है कि आप Maybe के अंदर IO क्रियाओं को जोड़ना चाहते हैं; एक फ़ंक्शन String -> Maybe (IO()) की कल्पना करें, जो वैधता के लिए स्ट्रिंग की जांच करता है, और यदि यह मान्य है, तो स्ट्रिंग से व्युत्पन्न कुछ जानकारी मुद्रित करने के लिए IO कार्रवाई लौटाता है। यह संभवतः हैस्केल के प्रथम श्रेणी के आईओ कार्यों के कारण संभव है।

लेकिन एक मोनैड में किसी अन्य मोनैड के कार्यों को निष्पादित करने की कोई क्षमता नहीं है जब तक कि आप इसे वह क्षमता न दें।

दरअसल, h = putStrLn "???" `seq` return() किसी भी IO भले ही यह putStrLn "???" के मूल्यांकन बलों या तो प्रदर्शन किया जा करने के लिए, कारण नहीं है।

+0

मैं एक मोनाड को किसी अन्य से क्रियाओं को निष्पादित करने की क्षमता कैसे दे सकता हूं, इसे मूल्यों के विरुद्ध पैटर्न मिलान की संभावना देकर? –

+3

उन तरीकों को लिखकर जो एक मोनैड को दूसरे में परिवर्तित करते हैं, या कुछ निष्पादन करते हैं। 'Control.Monad.ST.stToIO' उदाहरण के लिए, 'आईओ' गणना में 'एसटी' गणना को परिवर्तित करता है। –

+0

क्रिस्टल स्पष्ट। आप दोनों को धन्यवाद! –

4

चलो desugar!

h = do return (putStrLn "???"); return() 
-- rewrite (do foo; bar) as (foo >> do bar) 
h = return (putStrLn "???") >> do return() 
-- redundant do 
h = return (putStrLn "???") >> return() 
-- return for Maybe = Just 
h = Just (putStrLn "???") >> Just() 
-- replace (foo >> bar) with its definition, (foo >>= (\_ -> bar)) 
h = Just (putStrLn "???") >>= (\_ -> Just()) 

अब, क्या होता है जब आप h का मूल्यांकन? * ठीक है, हो सकता है, के लिए

(Just x) >>= f = f x 
Nothing >>= f = Nothing 

तो हम पैटर्न पहले मामले से मेल

f x 
-- x = (putStrLn "???"), f = (\_ -> Just()) 
(\_ -> Just()) (putStrLn "???") 
-- apply the argument and ignore it 
Just() 

सूचना है कि हम कैसे प्रदर्शन करने के लिए नहीं था इस अभिव्यक्ति का मूल्यांकन करने के लिए putStrLn "???"

* एनबी। यह कुछ हद तक अस्पष्ट है जिस बिंदु पर "desugaring" स्टॉप और "मूल्यांकन" शुरू होता है।यह आपके कंपाइलर के इनलाइनिंग निर्णयों पर निर्भर करता है। शुद्ध गणना का संकलन समय पर पूरी तरह से मूल्यांकन किया जा सकता है।

+1

desugaring के लिए धन्यवाद। एक नवागंतुक के लिए बहुत उपयोगी है। मुझे समझ में नहीं आता कि चीनी के साथ इतने सारे ट्यूटोरियल क्यों शुरू होते हैं। सबसे पहले रात का खाना, फिर रेगिस्तान। – masterxilo

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