2016-02-24 131 views
0

我通過得到一個IO字符串:更改功能支持IO字符串,而不是字符串

import Data.Char 
import Network.HTTP 
import Text.HTML.TagSoup 

openURL :: String -> IO String 
openURL x = getResponseBody =<< simpleHTTP (getRequest x) 

crawlType :: String -> IO String 
crawlType pkm = do 
    src <- openURL url 
    return . fromBody $ parseTags src 
    where 
    fromBody = unwords . drop 6 . take 7 . words . innerText . dropWhile (~/= "<p>") 
    url = "http://pokemon.wikia.com/wiki/" ++ pkm 

,我想通過解析它的數據:

getType :: String -> (String, String) 
getType pkmType = (dropWhile (== '/') $ fst b, dropWhile (== '/') $ snd b) 
        where b = break (== '/') pkmType 

但像你看到的,getType沒有按不支持IO字符串。

我是IO新手,那麼如何讓它工作? 我也tryed給IO字符串該功能時,理解錯誤,但它太複雜,我到現在:/

回答

7

首先,強調的是:IO String不是字符串。這是一個IO動作,當您將它綁定到main動作的某個位置時,將產生類型String的結果,但不應將其視爲某種類型的「字符串類型」的某種變體。相反,它是IO a類型的特殊實例。

出於這個原因,你幾乎可以肯定做不想「變化的功能支持IO String,而不是String 」。 而不是,您想要將此字符串接受函數應用於動作的結果。正如我所說的,這樣的結果是String,所以你很好。例如,

main :: IO() 
main = do 
    pkm = "blablabla" 
    typeString <- crawlType pkm 
    let typeSpec = getType typeString 
    print typeSpec -- or whatever you wish to do with it. 

您可以通過編寫和匕首省略typeString變量;

typeSpec <- getType <$> crawlType pkm 

如果您願意;這相當於什麼程序語言可能看起來像

var typeSpec = getType(crawlType(pkm)); 

或者,當然也可以包括在crawlType正確解析:

crawlType' :: String -> IO (String, String) 
crawlType' pkm = do 
    src <- openURL url 
    return . getType . fromBody $ parseTags src 
    where 
    fromBody = unwords . drop 6 . take 7 . words . innerText . dropWhile (~/= "<p>") 
    url = "http://pokemon.wikia.com/wiki/" ++ pkm 

&匕首;如果您好奇<$> operator的功能:這不是內置語法,如do/<-表示法。相反,它只是fmap的中綴版本,您可能會在其列表專用版本map中更好地瞭解它。這兩個列表[]IO都是functors,這意味着您可以通過普通函數來提取它們,僅更改元素/結果值,但不更改IO操作/列表脊柱的結構。

+0

這個答案太棒了。你幫了我很多。謝謝! –

相關問題