2011-02-23 13 views
7

हैलो महान वहाँ प्रोग्रामर,Haskell-समस्या: कब स्ट्रिंग -> [int]

मैं हास्केल में मेरी पहला कदम कर रहा हूँ और एक समारोह है कि confuses मुझे है:

import Data.List.Split 
getncheck_guesslist = do 
    line <- getLine 
    let tmp = splitOneOf ",;" line 
    map read tmp::[Int] 

splitOneOf है Data.List.Split में किसी प्रकार की अशुद्धता है कि वहाँ त्रुटि मैं समझ से splitOneOf :: (Eq a)=> [a]->[a]->[[a]]

(मैं कबाल स्थापित विभाजन के साथ इसे स्थापित) - लेकिन इस संघर्ष को हल करने के रूप में आईओ अब भी है पता नहीं है मेरे लिए एक रहस्य

मैं अल्पविराम या अर्धविराम से अलग पूर्णांकों का एक इनपुट पढ़ सकते हैं और पूर्णांकों की एक सूची तो प्राप्त करना चाहते हैं: इंट

  • कैसे

    • मैं कैसे जांच कर सकते हैं उपयोगकर्ता इनपुट प्रकार का है मैं "का अनुवाद" इनपुट [इंट] इसके लिए "आईओ स्ट्रिंग" प्रकार का है जो

    विचारों के लिए अग्रिम धन्यवाद और संकेत कर सकते हैं - तुम्हारा ε/2

  • +6

    यदि आईओ एक रहस्य है तो आपके पास दो विकल्प हैं: या तो आप इसे सीखकर इसका अनावरण करते हैं, या आप इसके बिना काम करते हैं और आईओ के बिना काम लिखते हैं। मैं थोड़ी देर के लिए दूसरे विकल्प के साथ जाने का सुझाव दूंगा। –

    उत्तर

    2

    यदि कुछ IO मोनैड के भीतर है, तो आप इसे आगे की प्रक्रिया के लिए शुद्ध बाहरी दुनिया में नहीं ले जा सकते हैं। इसके बजाय, आप अपने शुद्ध कार्यों को IO के भीतर कार्यों के अंदर काम करने के लिए पास करते हैं।

    अंत में, आपका प्रोग्राम कुछ इनपुट पढ़ता है और कुछ आउटपुट लिखता है, इसलिए आपका मुख्य कार्य IO के साथ काम करने जा रहा है, अन्यथा आप कुछ भी आउटपुट करने में सक्षम नहीं होंगे। इसके बजाय IO String पढ़ रहे हैं और एक [Int] बनाने के बजाय, कि [Int] अपने मुख्य कार्य में समारोह है कि खपत गुजरती हैं और do अंदर में उपयोग करें।

    12

    जब आप एक समारोह आईओ इकाई का उपयोग करता है लिख रहे हैं, किसी भी मूल्य तुम समारोह से वापस करना चाहते भी आईओ इकाई में होना चाहिए।

    इसका मतलब है कि, [Int] के साथ एक मान वापस करने के बजाय, आपको IO [Int] प्रकार के साथ कुछ वापस करना होगा। ऐसा करने के लिए, आप return समारोह है, जो IO में मूल्य (यह वास्तव में किसी भी इकाई के लिए काम करता है) "ऊपर लपेटता" का उपयोग करें। do-ब्लॉक desugaring (और सही करने से foo >>= return . bar को

    getncheck_guesslist = do 
        line <- getLine 
        let tmp = splitOneOf ",;" line 
        return (map read tmp :: [Int]) 
    
    2
    import Data.List.Split 
    import Control.Applicative 
    
    getncheck_guesslist :: IO [Int] 
    getncheck_guesslist = map read . splitOneOf ",;" <$> getLine 
    

    हर बार कोड का bogs नीचे है, जो तुम्हारा करता है:

    बस इस तरह return के साथ अपने मूल्य रैप करने के लिए, अंतिम पंक्ति को बदलने प्रकार की त्रुटि), तो आप अपने इकाई की monadic सुविधाओं का उपयोग नहीं कर रहे हैं, लेकिन केवल अपने functor हिस्सा है, कि, साफ कहा, तुम प्रकार के IO भाग के साथ खिलवाड़ नहीं कर रहे हैं, लेकिन IO a की a साथ:

    (<$>) :: (Functor f) => (a -> b) -> f a -> f b 
    

    (fmap<$> के लिए गैर-इंफिक्स नाम होगा। दोनों map से निकटता से संबंधित हैं।)

    कि कोड के ऊपर काफी तदर्थ कोड के लिए मुहावरेदार है, लेकिन साफ ​​कोड की तरह

    import Data.Maybe 
    
    maybeRead :: Read a => String -> Maybe a 
    maybeRead = fmap fst . listToMaybe . reads 
               -- That fmap is using "instance Functor Maybe" 
    
    parseGuessList :: String -> [Int] 
    parseGuessList = catMaybes . map maybeRead . splitOneOf ",;" 
    
    getncheck_guesslist = parseGuessList <$> getLine 
    

    लगेगा, या वैकल्पिक रूप से, अगर आप गैर पूर्णांक इनपुट लेकिन त्रुटि को अनदेखा नहीं करना चाहते बाहर,

    parseGuessList xs = if success then Just . catMaybes $ ys else Nothing 
        where ys :: String -> [Mabye Int] 
         ys = map maybeRead . splitOneOf ",;" $ xs 
         success = all isJust ys 
    

    (खबरदार, हालांकि, मैं केवल कि कोड सही सिद्ध कर दिया है, वास्तव में यह करने की कोशिश की नहीं।)

    यह किसी भी अधिक है कि तुलना में जटिल आप एक उचित पार्स तुला का उपयोग करना चाहें हो जाता है आरई, मुझे लगता है।

    +0

    यह मेरे सिर पर बस गया। मैं डाउनवोट नहीं जा रहा हूं, लेकिन मुझे लगता है कि यह मूल पोस्टर के सिर पर भी चला गया है। – Zach

    7

    "सही तरीके से" हास्केल में यह करने के लिए, से अच्छी तरह से, बाकी सब आईओ अलग करने के लिए है। अपने कोड के प्रत्यक्ष अनुवाद इस होगा:

    getncheck_guesslist :: IO [Int] 
    getncheck_guesslist = do line <- getLine    -- get 
             return (check_guesslist line) -- check 
    
    check_guesslist :: String -> [Int] 
    check_guesslist line = let tmp = splitOneOf ",;" line 
             in map read tmp 
    

    सूचना है कि getncheck_guesslist बस एक आईओ कार्रवाई है। फ़ंक्शन में पैरामीटर इनपुट नहीं है, भले ही (आईओ) इनपुटgetLine से इसकी आवश्यकता हो।

    यह भी ध्यान दें कि getncheck_guesslistgetLine आईओ क्रिया का एक साधारण संशोधन है। क्या कोई संयोजक नहीं है जो मुझे एक मोनैड के अंदर मूल्य पर कार्य करने के लिए एक समारोह को धक्का दे सकता है? रूक जा। होगल समय!

    मैं एक समारोह (a -> b) है। मेरे पास इनपुट प्रकार का मूल्य है, लेकिन यह एक मोनड m a में फंस गया है। मैं मोनैड के अंदर समारोह करना चाहता हूं, इसलिए परिणाम अनिवार्य रूप से मोनड में भी m b में फंस जाएगा। यह सब एक साथ रखकर, हम (a -> b) -> m a -> m b hoogle। लो और देखें, fmap वही है जो हम खोज रहे थे।

    get_guesslist = check_guesslist `fmap` getLine 
    -- or, taking it a step further 
    get_guesslist = (map read . splitOneOf ",;") `fmap` getLine :: IO [Int] 
    

    एक अंतिम ध्यान दें, जब भी आप somethingAndSomethingElse की तरह नाम के साथ एक विधि कोड के रूप में, यह आमतौर पर बेहतर कोडिंग शैली लिख सकते हैं और दो अलग-अलग तरीके के रूप में something और somethingElse आह्वान करने के लिए है। अंतिम संस्करणों के लिए, मैंने इसका नाम बदलकर get_guesslist रखा है, क्योंकि संकल्पनात्मक रूप से यह वही है। यह अनुमानों की सूची के रूप में अनुमान लगाता है।

    अंतिम अंतिम नोट के रूप में, मैंने उस बिंदु पर छोड़ा है जहां बारसप शुरू हुआ था। ;) fmap<$> जैसा ही है।

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