2011-12-24 13 views
5

मैं हास्केल के लिए नया हूं और इसकी कुछ अवधारणाओं के आस-पास अपने सिर को लपेटने में कुछ कठिनाइयां हैं।आईओ [[स्ट्रिंग]] कैसे फ़्लैट करें?

आईओ के साथ खेलते समय मैं एक आईओ [[स्ट्रिंग]] को फ़्लैट करना चाहता था।

मैं क्या कोशिश की है का एक उदाहरण:

module DatabaseTestSO where 

import Database.HDBC 
import Database.HDBC.MySQL 
import Data.Foldable 

convSqlValue :: [SqlValue] -> [String] 
convSqlValue xs = [ getString x | x <- xs ] 
    where getString value = case fromSql value of 
       Just x -> x 
       Nothing -> "Null" 

listValues :: [[SqlValue]] -> [[String]] 
listValues [] = [] 
listValues xs = [ convSqlValue x | x <- xs ] 

flatten :: [[a]] -> [a] 
flatten = Data.Foldable.foldl (++) [] 

domains :: IO [[String]] 
domains = 
    do conn <- connectMySQL defaultMySQLConnectInfo { 
       mysqlHost  = "hostname", 
       mysqlDatabase = "dbname", 
       mysqlUser  = "username", 
       mysqlPassword = "pass" } 

     queryDomains <- quickQuery conn "SELECT name FROM domains" [] 

     return (listValues queryDomains) 

कि GHCi में [[String]] साथ काम करता है के रूप में उम्मीद:

*DatabaseTestSO> flatten [["blah","blab","wah"],["bloh","blob","woh"],["blih","blib","wuh"]] 
["blah","blab","wah","bloh","blob","woh","blih","blib","wuh"] 

लेकिन IO [[String]] जहाँ मैं

*DatabaseTestSO> flatten domains 

<interactive>:1:9: 
    Couldn't match expected type `[[a0]]' 
       with actual type `IO [[String]]' 
    In the first argument of `flatten', namely `domains' 
    In the expression: flatten domains 
    In an equation for `it': it = flatten domains 

पाने के साथ नहीं है मुझे लगता है कि मैं ऐसे फ़ंक्शन का उपयोग नहीं कर सकता जो आईओ प्रकारों के साथ शुद्ध होना चाहिए? क्या मैं IO [[String]] से [[String]] पर परिवर्तित कर सकता हूं? मैं इस समस्या को सही ढंग से कैसे हल करूं?

+4

'flatten' को 'concat' कहा जाता है और इसे 'प्रीलूड' में परिभाषित किया जाता है। –

+0

मैं देखता हूं। जीएचसीआई का उपयोग नहीं करते समय 'प्रीलूड' स्वचालित रूप से आयात किया जाता है? –

+0

हां (फिलर ...) –

उत्तर

15

आपको यह समझना होगा कि IO something का अर्थ क्या है। यह something नहीं है, यह क्रिया है जो something लौटाएगी (इस मामले में, something[[String]] है)। इसलिए, जब तक आप कार्रवाई नहीं करते हैं, तब तक आप उस कार्यवाही के साथ कुछ भी नहीं कर सकते हैं, जो उस कार्य को लौटाता है।

आपके पास अपनी समस्या का समाधान करने के लिए दो विकल्प हैं।

  1. कार्रवाई करें, और परिणाम का उपयोग करें। यह इस तरह से किया जाता है:

    do 
        ds <- domains  -- Perform action, and save result in ds 
        return $ flatten ds -- Flatten the result ds 
    
  2. है कि कुछ कार्रवाई के परिणाम लेता है कोई नया कार्य बनाएँ, और यह करने के लिए एक समारोह लागू होता है। नई कार्रवाई तब परिवर्तित मूल्य लौटाती है। यह मॉड्यूल में liftM फ़ंक्शन के साथ किया जाता है।

    import Control.Monad 
    -- ... 
    
    do 
        -- Creates a new action that flattens the result of domains 
        let getFlattenedDomains = liftM flatten domains 
    
        -- Perform the new action to get ds, which contains the flattened result 
        ds <- getFlattenedDomains 
    
        return ds 
    

पी एस। आप यह समझाने के लिए अपने domains वैरिएबल को getDomains पर पुनर्नामित करना चाहेंगे। यह शुद्ध मूल्य नहीं है; यह एक monadic कार्रवाई है जो एक शुद्ध मूल्य देता है।

+0

आपकी व्याख्या बहुत उपयोगी थी। –

+3

नोट: 'fmap' =' liftM' = 'liftA' =' <$> '। –

10

आपको आईओ के "बाहर" कुछ भी नहीं मिल सकता है, तो आपको इसके अंदर काम करने के लिए flatten उठाना है। ऐसा करने का सबसे आसान तरीका fmap - map की तरह समायोजित करें, एक सूची पर एक फ़ंक्शन लागू होता है, fmap उदाहरण, जैसे कि IO पर फ़ंक्शन लागू करता है।

flattenIO xs = fmap flatten xs 

अधिक सामान्य मामलों में, आप do संकेतन का उपयोग IO संगणना में चीजों को पाने के लिए कर सकते हैं। उदाहरण के लिए:

flattenIO xs = do ys <- xs 
        return (flatten ys) 

... जो सिर्फ इस मामले में fmap लेखन की एक राउंडअबाउट तरीका है।

+0

आपके उत्तर के लिए धन्यवाद। मुझे बहुत कुछ सीखना होगा। –

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