2014-04-07 3 views
0

간단한 sitemap.xml 크롤러를 작성하고 있습니다. 코드는 다음과 같습니다. 제 질문은 main의 끝에있는 코드가 아무 것도 인쇄하지 않는 이유입니다. 나는 하스켈의 lazyness 때문이다 의심하지만, 여기에 대처하는 방법을 알고하지 않습니다하스켈이 블록을 평가하지 않습니다.

import Network.HTTP.Conduit 
import qualified Data.ByteString.Lazy as L 
import Text.XML.Light 
import Control.Monad.Trans (liftIO) 
import Control.Monad 
import Data.String.Utils 
import Control.Exception 

download :: Manager -> Request -> IO (Either HttpException L.ByteString) 
download manager req = do 
    try $ 
    fmap responseBody (httpLbs req manager) 

downloadUrl :: Manager -> String -> IO (Either HttpException L.ByteString) 
downloadUrl manager url = do 
    request <- parseUrl url 
    download manager request 

getPages :: Manager -> [String] -> IO [Either HttpException L.ByteString] 
getPages manager urls = 
    sequence $ map (downloadUrl manager) urls 

main = withManager $ \ manager -> do 
    -- I know simpleHttp is bad here 
    mapSource <- liftIO $ simpleHttp "http://example.com/sitemap.xml" 

    let elements = (parseXMLDoc mapSource) >>= Just . findElements (mapElement "loc") 
     Just urls = liftM (map $ (replace "/#!" "?_escaped_fragment_=") . strContent) elements 
     mapElement name = QName name (Just "http://www.sitemaps.org/schemas/sitemap/0.9") Nothing 

    return $ 
    getPages manager urls >>= \ pages -> do 
     print "evaluate me!" 
     sequence $ map print pages 
+0

왜'return'에'getPages'를 래핑하고 있습니까? 불필요한 것처럼 보입니다. – arrowd

+0

@arrowdodger 반환하지 않고 컴파일 오류가 발생했습니다. 'IO'유형 'IO'와 일치하지 않습니다. with 'Control.Monad.Trans.Resource.Internal.ResourceT m' 예상 유형 : Control.Monad.Trans.Resource.Internal.ResourceT m [모두 HttpException L.ByteString] 실제 유형 : IO [모두 HttpException L.ByteString]' –

답변

2

적어도 여기에 설명 된 것과 동일한 문제가 발생합니다. 실제로는 유형 오류가 발생하면 typechecks라는 잘못된 코드가 있습니다. Why is the type of "Main.main", "IO()" and not "IO a"?. 따라서 main에 형식 서명 main :: IO()을 명시 적으로 지정해야합니다.

liftreturn을 대체 할 것, 문제를 해결 ( http://hackage.haskell.org/package/transformers/docs/Control-Monad-Trans-Class.html#v:lift 참조) mapM_sequence $ map ...를 교체하십시오. mapM_ fsequence_ . map f과 같습니다.

+0

감사합니다. 이제는 명확한 타이핑과 모듈화가 어디에서나 승리 할 수 ​​있다는 것을 알고 있습니다. 다음은 작동중인 버전입니다. https://gist.github.com/wishbear/10119638 –

2

이 마지막 returnrunResourceT (http://hackage.haskell.org/package/resourcet-1.1.1/docs/Control-Monad-Trans-Resource.html#v:runResourceT)로 대체합니다. 유형에서 알 수 있듯이 ResourceT가 IO 작업으로 바뀝니다.

+0

하지만 컴파일러 (및 워드 프로세서)는 IO (http://hackage.haskell.org/package/)가 아닌 ResourceT가 필요하다고 말합니다. http-conduit-1.2.0/docs/Network-HTTP-Conduit.html # g : 4) –

+0

아, 이제 알겠습니다. 'safeFromIOBase'가 필요합니다 : http://hackage.haskell.org/package/conduit-0.1.1.1/docs/Control-Monad-Trans-Resource.html#v:safeFromIOBase – arrowd

관련 문제