2010-12-21 10 views
10

के लिए मोनाडप्लस परिभाषा मैं केवल कोड का एक त्वरित कोड लिख रहा था, और मैं आईओ मोनाड में guard function का उपयोग करना चाहता था। हालांकि, no definition of MonadPlus for IO है जिसका अर्थ है कि हम आईओ भूमि में गार्ड का उपयोग नहीं कर सकते हैं। मैंने an example of using the MabyeT transformer to use guard in the Maybe Monad देखा है और फिर सभी आईओ कार्यों को उठाया है, लेकिन अगर मुझे ऐसा नहीं करना है तो मैं वास्तव में ऐसा नहीं करना चाहता हूं।हास्केल आईओ

मैं क्या हो सकता है चाहता हूँ के कुछ उदाहरण:

handleFlags :: [Flag] -> IO() 
handleFlags flags = do 
    when (Help `elem` flags) (putStrLn "Usage: program_name options...") 
    guard (Help `elem` flags) 
    ... do stuff ... 
    return() 

अगर वहाँ एक गार्ड समारोह (या कुछ इसी तरह) आईओ इकाई में MonadPlus या अन्यथा के लिए एक घोषणा के माध्यम से प्राप्त करने के लिए एक अच्छा तरीका था मैं सोच रहा था । या शायद मैं यह गलत कर रहा हूँ; ऊपर दिए गए फ़ंक्शन में उस सहायता संदेश को लिखने का एक बेहतर तरीका है? धन्यवाद।

(पी एस मैं अगर-तो-और कुछ बयानों लेकिन यह। किसी भी तरह बिंदु को हराने के लिए नहीं विकल्प यह घोंसले की एक बड़ी राशि में परिणाम होगा की एक बहुत कुछ के लिए है कि उल्लेख करने के लिए लगता है इस्तेमाल कर सकते हैं।)

उत्तर

20

MonadPlus की परिभाषा पर विचार करें? IO a का मान एक आईओ गणना का प्रतिनिधित्व करता है जो a प्रकार का कुछ देता है, इसलिए mzero किसी भी संभावित प्रकार को वापस करने के लिए आईओ गणना करना होगा। जाहिर है, कुछ मनमानी प्रकार के लिए मूल्य को अपनाने का कोई तरीका नहीं है, और Maybe के विपरीत कोई भी "खाली" कन्स्ट्रक्टर नहीं है जिसका उपयोग हम कर सकते हैं, इसलिए mzeroआवश्यक रूप से एक आईओ गणना का प्रतिनिधित्व करेगा जो कभी नहीं लौटाता है।

आप आईओ गणना कैसे लिखते हैं जो कभी वापस नहीं आती है? या तो एक अनंत लूप में जाएं या मूल रूप से रनटाइम त्रुटि फेंक दें। पूर्व संदिग्ध उपयोगिता का है, इसलिए उत्तरार्द्ध वह है जिसे आप फंस गए हैं।

संक्षेप में, IO के लिए MonadPlus का एक उदाहरण लिखने के लिए है कि आप क्या चाहते हैं यह है: mzero एक क्रम अपवाद है, और mplus जबकि mzero द्वारा फेंका किसी भी अपवाद को पकड़ने में अपनी पहली तर्क का मूल्यांकन किया है। यदि कोई अपवाद नहीं उठाया जाता है, तो परिणाम वापस कर दें। यदि कोई अपवाद उठाया जाता है, तो अपवादों को अनदेखा करते समय mplus का दूसरा तर्क का मूल्यांकन करें।

उस ने कहा, रनटाइम अपवादों को अक्सर अवांछनीय माना जाता है, इसलिए मैं उस रास्ते पर जाने से पहले संकोच करूंगा। यदि आप इसे इस तरह से करना चाहते हैं (और इस बात को बढ़ाने में कोई फर्क नहीं पड़ता कि आपका प्रोग्राम रनटाइम पर क्रैश हो सकता है) तो आपको उपर्युक्त को Control.Exception में लागू करने के लिए आवश्यक सब कुछ मिल जाएगा।

व्यवहार में, मैं शायद या तो इकाई ट्रांसफार्मर दृष्टिकोण का उपयोग करता है, तो मैं monadic भाव, या अगर सशर्त का सबसे समारोह तर्क के रूप में प्रदान शुद्ध मूल्यों पर निर्भर का मूल्यांकन के परिणाम पर ing guard का एक बहुत चाहता था चाहते हैं (जो आपके उदाहरण में झंडे हैं) पैटर्न गार्ड का उपयोग @ एंथनी के जवाब में करें।

+0

है तो यह एक उत्कृष्ट जवाब है और यह मुझे समझने देता है कि आईओ के लिए मोनाडप्लस वास्तव में क्यों बनाता है त्रुटियों या अनंत लूप के बिना कोई समझ नहीं है। –

+1

@Robert Massaioli: जो कहने के लिए कुछ भी नहीं है * गलत * है। यह एक बिल्कुल सही 'मोनाडप्लस' उदाहरण है, यह 'मोनाडप्लस' त्रुटि के मोनैड के रूप में 'या तो ई' का उपयोग करने के लिए कैसे काम करता है, और मुझे लगता है कि 'आईओ' के लिए ऐसा एक उदाहरण भी मोनैड ट्रांसफार्मर पुस्तकालयों में से एक में मौजूद है। एकमात्र समस्या यह है कि आपको त्रुटियों को पकड़ने के बारे में और अधिक सावधान रहना होगा, क्योंकि 'हो सकता है' या इस तरह के अपवाद, 'मुख्य' तक सभी तरह से बच सकते हैं। –

8

मैं करता हूँ गार्ड के साथ इस तरह की चीज।

class Monad m => MonadPlus m where 
    mzero :: m a 
    mplus :: m a -> m a -> m a 

आप IO के लिए mzero कैसे लागू होगा:

handleFlags :: [Flag] -> IO() 
handleFlags flags 
    | Help `elem` flags = putStrLn "Usage: program_name options..." 
    | otherwise = return() 
+2

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

+1

ध्यान दें कि cmdargs जैसी लाइब्रेरी हैं जो आपके लिए ऐसी चीजों से निपटती हैं :) –

+0

fwiw, cmdargs में मेरी पसंद के लिए बहुत अधिक जादू है। मैं parseargs पसंद करते हैं क्योंकि यह सब ऊपर बोर्ड है। – sclv

0

इसके लिए फ़ंक्शंस ठीक से किए गए हैं: Control.Monad में, when और इसके समकक्ष unless फ़ंक्शन। एंथोनी के जवाब में इस तरह के रूप में लिखा जा सकता है:

handleFlags :: [Flag] -> IO() 
handleFlags flags = 
    when (Help `elem` flags) $ putStrLn "Usage: program_name options..." 

विनिर्देशों:

when :: (Applicative m) => Bool -> m() -> m() 
unless bool = when (not bool) 

Link to docs on hackage.haskell.org

तो अधिक की जरूरत है, यहाँ एक link to another package, specifically monad-oriented and with several more utilities: Control.Monad.IfElse