2012-08-18 13 views
6

के साथ अपेक्षित प्रकार 'आईओ ए0' से मेल नहीं खा सकता है, मैं हास्केल में नया हूं, और मैं समझने की कोशिश करता हूं कि आईओ को सही तरीके से कैसे करना है।हास्केल आईओ: वास्तविक प्रकार

ठीक निम्नलिखित काम करता है:

main = do 
    action <- cmdParser 
    putStrLn "Username to add to the password manager:" 
    username <- getLine 
    case action of 
    Add -> persist entry 
     where 
     entry = Entry username "somepassword" 

संकलन त्रुटि में निम्न परिणाम जबकि:

main = do 
    action <- cmdParser 
    case action of 
    Add -> persist entry 
     where 
     entry = Entry promptUsername "somepassword" 

promptUsername = do 
    putStrLn "Username to add to the password manager:" 
    username <- getLine 

त्रुटि यहाँ है:

Couldn't match expected type `IO b0' with actual type `[Char]' 
Expected type: IO b0 
    Actual type: String 
In the expression: username 
[...] 

यहाँ क्या चल रहा है? पहला संस्करण क्यों काम करता है, जबकि दूसरा नहीं करता है?

मुझे पता है कि स्टैक ओवरफ़्लो में इस तरह के कुछ समान प्रश्न हैं, लेकिन उनमें से कोई भी मुझे इस समस्या की व्याख्या करने लग रहा था।

उत्तर

8

usernameString है, लेकिन promptUsername एक IO String है। आपको कुछ ऐसा करने की ज़रूरत है:

username <- promptUsername 
let entry = Entry username "somepassword" 
persist entry 
+5

पर कार्रवाई करेंगे I यह एक भ्रमित एक भ्रमित है। कोड 'डू {ए; बी <- सी; डी बी}' वास्तव में 'a >> = \ _ -> c >> = \ b -> d b' के लिए एक शॉर्टेंड है। जो लोग अनिवार्य दुनिया से आते हैं, वे '<-'' असाइनमेंट ऑपरेटर के रूप में सोचते हैं। यह नहीं। डू-नोटेशन में प्रत्येक पंक्ति अज्ञात फ़ंक्शन में अनुवाद करती है, और '<-' इस तरह के फ़ंक्शन के तर्क का तर्क देती है। मोनैड और उनके व्यावहारिक अनुप्रयोगों से परिचित होने के बारे में पढ़ने के लिए दृढ़ता से प्रोत्साहित किया जाना चाहिए। – permeakra

+0

मैं वास्तव में monads पर ज्ञान के बिना समस्या और समाधान को समझने में सक्षम था। –

0

यहां एक और संस्करण है।

main = do 
    action <- cmdParser 
    case action of 
    Add -> do username <- promptUsername 
       let entry = Entry username "somepassword" 
       persist entry 

promptUsername :: IO String 
promptUsername = do 
    putStrLn "Username to add to the password manager:" 
    getLine 

-- fake definitions to make things compile 

persist :: Entry -> IO() 
persist = print 

cmdParser :: IO Add 
cmdParser = fmap (const Add) getLine 

data Add = Add deriving Show 
data Entry = Entry String String deriving Show 

समस्या सिर्फ इतना है कि promptUsername एक कार्रवाई नहीं एक स्ट्रिंग है। कार्रवाई 'एक स्ट्रिंग लौटाती है', इसलिए इसमें IO String टाइप है, लेकिन यह स्ट्रिंग की तरह कुछ भी नहीं है। चूंकि Entry x y को x स्थिति में String की आवश्यकता होती है, एक्शन के आकार में कुछ संख्या या बूलियन की तुलना में कहीं अधिक फिट नहीं हो सकती है। तो अपनी जटिल कार्रवाई को परिभाषित करने में, main, आपको स्ट्रिंग को 'निकालना' चाहिए जो निष्पादन के किसी भी मामले में सरल कार्रवाई promptUsername से परिणामस्वरूप होगा, और प्रविष्टि के पहले तर्क के रूप में String दें। फिर आप persist परिणामस्वरूप Entry

+0

धन्यवाद! Http://learnyouahaskell.com/input-and-output में आपका बिंदु भी समझाया गया है। आम तौर पर, मुझे लगता है कि आप महान अच्छे के लिए एक हास्केल सीखें! रियल वर्ल्ड हास्केल (http://book.realworldhaskell.org/) से समझना आसान है। –

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