2013-04-22 42 views
2

我工作的項目的子節點我正在這裏進行動作的功能:我需要

How do I make a do block return early?

我與我的功能單子轉換方法去看起來是這樣的:

scrapePost :: String -> IO()             
scrapePost url = liftM (fromMaybe()) . runMaybeT $ do 
    doc <- lift $ fromUrl url 
    -- get a bunch of stuff from the page 
    -- send it to the db 
    replies <- lift . runX $ doc >>> css ".post.reply" 
    -- here is the problem 
    mapM_ (parseReply url (fromJust page_id)) replies 
    -- here is the problem 

parseReply是我需要的功能,但我似乎無法做到正確。

這裏是我的軟弱試圖啓動功能:

parseReply :: String -> String -> XNode -> Maybe()         
parseReply url op_id reply = do              
    reply_id <- runX $ reply ! "id"              
    return()      

順便說一句,我使用HandsomeSoup

我將工作就像用一組CSS規則刮scrapePost功能,降回答說,沒有所有的值,並將它們發送到數據庫。

我想使用mapM,因爲我希望將mapM全部替換爲liftIO並查看性能差異。

[更新]

因此,原來我並不需要做任何類型的雜技,我只是需要一種方法來打開回復節點到我發現here根節點。

由於parseReply僅用於MaybeT IO()上下文中,因此其類型不需要更改,並且scrapePost可以保持不變。

parseReply變爲:

toRoot :: ArrowXml a => XmlTree -> a n XmlTree          
toRoot node = root [] [constA node]             

parseReply :: String -> String -> XmlTree -> MaybeT IO()       
parseReply url op_id reply = do              
    let node = toRoot reply               
    reply_id <- lift . liftM (`atMay` 0) $ runX $ node >>> css "div" ! "id" 
    guard (isJust reply_id)               
    return() 

回答

5

讓我們來看看你的「單子選手」

liftM (fromMaybe()) . runMaybeT :: MaybeT IO() -> IO() 

所以我們需要做塊的每一行有型MaybeT IO()的類型。由於mapM_ :: (a -> m b) -> [a] -> m()我們有parseReply url (fromJust page_id)需要有類型MaybeT IO()不只是Maybe()

幸運的,因爲人們可能希望,很容易注入純MaybeMaybeT IO

parseReplyT :: Monad m => String -> String -> XNode -> MaybeT m() 
parseReplyT url op_id = MaybeT . return . parseReply url op_id