2013-03-15 26 views
13

Haskell'i kullanarak bir web sayfası için kazımak ve sonuçları bir nesneye derlemeye çalışıyorum.Nasıl bir blok geri dönüşü erken yapabilirim?

Neden olursa olsun, sayfalardaki tüm öğeleri alamıyorum, sayfayı işlemeyi ve erken dönmeyi denemeyi bırakmak istiyorum. Örneğin

:

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() 

sorun do bloğunu durdurmak veya çalıştırılmak üzere diğer bölümleri tutmaz when olduğunu.

Bunu yapmanın doğru yolu nedir?

+1

İstediğiniz bu mu? http://www.haskellforall.com/2012/07/breaking-from-loop.html –

cevap

14

return. Bunun yerine, return'un yaptığı, bir monoya bir değer enjekte etmektir (bu durumda IO). Sen seçenekler

en basit bir çift

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() 

başka bir seçenek IO monad yok ki burada 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() 

genel sorun kullanmak istiyorsa kullanmaktır var kontrol etkileri (istisnalar hariç). Yukarıdaki kod hiçbiri olmuştur: Eğer gerçekten 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() 

UYARI kullanmak gerekir tam şişmiş kontrol etkileri almak istiyorsanız Öte yandan, belki monad trafo

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() 

kullanabilirsiniz test edildi, hatta kontrol edildi!

+0

İkinci yaklaşım benim için iyi çalıştı. Sana yapmak nee düşünüyorum 'sürece (koşul) $ do' o ('$' fark) derlemek için – kunigami

2

Haskell ile daha önce hiç çalışmamıştım, ama bence kolay görünüyor. when (isNothing date) $ exit()'u deneyin. Bu da çalışmıyorsa, ifadenizin doğru olduğundan emin olun. Ayrıca daha fazla bilgi için bu web sitesine bakın: Breaking From loop.

+4

İyi bağlantı, ancak "çıkış" ın örnekte tanımlandığını ve bir yerleşik olmadığını fark edin. Bu yazıdaki çözüm, @ dave4420'nin çözümü ile aynıdır: bir monad transformatörü. – luqui

12

Monad trafo kullanın! Erken dönüş, throwError/eitherT/EitherT yerine mzero/maybeT/MaybeT kullanmak dönüş değeri daha fazla esneklik için

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() 

. (O zaman guard kullanamazsınız rağmen.)

(Muhtemelen de yerine headMay ait headZ kullanabilir ve açık guard hendek.) Diğer dillerde return aynı şeyi yapmaz Haskell

+1

'Control.Error.Util' için ne gerekiyor? –

+1

@Joehillen 'belkiT'. – dave4420

İlgili konular