2013-03-15 2 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() 

문제는 DO 블록을 중지하거나 실행되는 다른 부분을 유지하지 않는 when입니다.

어떻게해야할까요?

+1

이게 원하는가요? http://www.haskellforall.com/2012/07/breaking-from-loop.html –

답변

14

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

또 다른 옵션은 IO 모나드가없는 것이 여기 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() 

일반적인 문제를 사용하는 경우 사용하는 것입니다해야 제어 효과 (예외 제외). 위의 코드 중 어느 것도 없었다 : 당신이 정말 당신이 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() 

경고를 사용할 필요가 만발한 제어 효과를 얻으려면 다른 한편으로는, 당신은 아마 모나드 변압기

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

를 사용할 수 있습니다 테스트를 거쳤거나 유형을 확인했습니다!

+0

두 번째 접근 방식은 저에게 효과적이었습니다. 나는 네가 할 것 같아. '(조건) $ do' 컴파일하기 위해 ('$'에주의하십시오.) – kunigami

2

저는 하스켈과 함께 일한 적이 없지만 쉽게 이해할 수 있습니다. 시도하십시오 when (isNothing date) $ exit(). 이 방법도 효과가 없으면 진술 내용이 올바른지 확인하십시오. 자세한 정보는이 웹 사이트를 참조하십시오 : Breaking From loop.

+4

링크가 좋지만 'exit'는 예제에 정의되어 있으며 내장되어 있지 않습니다. 이 게시물의 솔루션은 @ dave4420의 솔루션 인 모나드 변환기와 같습니다. – luqui

12

모나드 변환기를 사용하십시오! 일찍 복귀, throwError/eitherT/EitherT 대신 mzero/maybeT/MaybeT를 사용하여 반환 값에 더 많은 유연성을

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

. (다음 guard를 사용할 수 있습니다.)

(아마 대신 headMayheadZ를 사용하여 명시 적 guard 도랑.) 다른 언어 return 같은 일을하지 않는 하스켈

+1

'Control.Error.Util'은 무엇을 위해 필요합니까? –

+1

@Joehillen'maybeT'. – dave4420

관련 문제