2013-03-15 6 views
13

मैं हास्केल का उपयोग करके एक वेबपृष्ठ के लिए स्क्रैप करने की कोशिश कर रहा हूं और परिणामों को किसी ऑब्जेक्ट में संकलित कर रहा हूं।मैं जल्दी से ब्लॉक ब्लॉक कैसे कर सकता हूं?

यदि, किसी भी कारण से, मुझे पृष्ठों से सभी आइटम नहीं मिल सकते हैं, तो मैं पृष्ठ को संसाधित करने और जल्दी लौटने की कोशिश करना बंद करना चाहता हूं।

उदाहरण के लिए:

scrapePage :: String -> IO() 
scrapePage url = do 
    doc <- fromUrl url 
    title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText 
    when (isNothing title) (return()) 
    date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc" 
    when (isNothing date) (return()) 
    -- etc 
    -- make page object and send it to db 
    return() 

समस्या when है करते ब्लॉक रोक नहीं करता है या निष्पादित किया जा रहा से अन्य भागों रखने के लिए।

ऐसा करने का सही तरीका क्या है?

+1

क्या आप यह चाहते हैं? http://www.haskellforall.com/2012/07/breaking-from-loop.html –

उत्तर

14

Haskell अन्य भाषाओं में return के रूप में एक ही बात नहीं करता है में return। इसके बजाय, return क्या एक मानदंड में एक मान इंजेक्ट करना है (इस मामले में IO)। आप विकल्पों

सबसे सरल की एक जोड़ी अगर

scrapePage :: String -> IO() 
scrapePage url = do 
    doc <- fromUrl url 
    title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText 
    if (isNothing title) then return() else do 
    date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc" 
    if (isNothing date) then return() else do 
    -- etc 
    -- make page object and send it to db 
    return() 

एक और विकल्प unless

scrapePage url = do 
    doc <- fromUrl url 
    title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText 
    unless (isNothing title) do 
    date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc" 
    unless (isNothing date) do 
     -- etc 
     -- make page object and send it to db 
     return() 

सामान्य समस्या यहाँ उपयोग करने के लिए है IO इकाई नहीं है वह यह है कि उपयोग करने के लिए है नियंत्रण प्रभाव (अपवादों को छोड़कर)। दूसरी ओर, आप शायद इकाई ट्रांसफार्मर

scrapePage url = liftM (maybe() id) . runMaybeT $ do 
    doc <- liftIO $ fromUrl url 
    title <- liftIO $ liftM headMay $ runX $ doc >>> css "head.title" >>> getText 
    guard (isJust title) 
    date <- liftIO $ liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc" 
    guard (isJust date) 
    -- etc 
    -- make page object and send it to db 
    return() 

इस्तेमाल कर सकते हैं यदि आप वास्तव में पूर्ण विकसित नियंत्रण प्रभाव आप उपयोग करना ContT

scrapePage :: String -> IO() 
scrapePage url = runContT return $ do 
    doc <- fromUrl url 
    title <- liftM headMay $ runX $ doc >>> css "head.title" >>> getText 
    when (isNothing title) $ callCC ($()) 
    date <- liftM headMay $ runX $ doc >>> css "span.dateTime" ! "data-utc" 
    when (isNothing date) $ callCC ($()) 
    -- etc 
    -- make page object and send it to db 
    return() 

चेतावनी की जरूरत प्राप्त करना चाहते हैं: उपरोक्त कोड में से कोई भी कर दिया गया है परीक्षण किया, या यहां तक ​​कि टाइप की जाँच की!

+0

दूसरे दृष्टिकोण ने मेरे लिए अच्छा काम किया। मुझे लगता है कि आप 'जब तक (शर्त) $ 0' संकलित करने के लिए (' $ 'पर ध्यान दें) – kunigami

2

मैंने कभी हास्केल के साथ काम नहीं किया है, लेकिन ऐसा लगता है कि यह आसान है। when (isNothing date) $ exit() आज़माएं। यदि यह भी काम नहीं कर रहा है, तो सुनिश्चित करें कि आपका कथन सही है। अधिक जानकारी के लिए यह वेबसाइट भी देखें: Breaking From loop

+4

अच्छा लिंक, लेकिन ध्यान दें कि 'निकास' को उदाहरण में परिभाषित किया गया है और यह एक अंतर्निहित नहीं है। उस पोस्ट का समाधान @ डेव 4420 के समाधान के समान है: एक मोनड ट्रांसफॉर्मर। – luqui

12

एक मोनड ट्रांसफॉर्मर का उपयोग करें!

import Control.Monad.Trans.Class -- from transformers package 
import Control.Error.Util  -- from errors package 

scrapePage :: String -> IO() 
scrapePage url = maybeT (return()) return $ do 
    doc <- lift $ fromUrl url 
    title <- liftM headMay $ lift . runX $ doc >>> css "head.title" >>> getText 
    guard . not $ isNothing title 
    date <- liftM headMay $ lift . runX $ doc >>> css "span.dateTime" ! "data-utc" 
    guard . not $ isNothing date 
    -- etc 
    -- make page object and send it to db 
    return() 
वापसी मान में और अधिक लचीलापन है जब आप जल्दी वापसी, throwError/ eitherT/ EitherT बजाय mzero/ maybeT/ MaybeT उपयोग

। (हालांकि तो आप guard उपयोग नहीं कर सकते।)

(शायद भी headMay के बजाय headZ का उपयोग करें और स्पष्ट guard खाई।)

+1

'Control.Error.Util' के लिए क्या आवश्यक है? –

+1

@ जोहेलीन 'होट टी'। – dave4420

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