0

シンプルな sitemap.xml クローラーを作成しています。コードは以下のとおりです。私の質問は、最後のコードがmain何も出力しない理由です。Haskellの怠惰が原因だと思いますが、ここで対処する方法がわかりません:

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
4

2 に答える 2

2

ここで説明したのと同じ問題が発生しています。少なくとも、実際に型エラーを発生させる必要があるときに型チェックを行う誤ったコードがある限り、"Main.main" の型が "IO ()" ではなく " IO a"? . mainこれが、型シグネチャを常にmain :: IO ()明示的に与える必要がある理由です。

この問題を解決するには、return( lifthttp://hackage.haskell.org/package/transformers/docs/Control-Monad-Trans-Class.html#v:lift を参照)に置き換え、 に置き換えsequence $ map ...ますmapM_mapM_ fと同等sequence_ . map fです。

于 2014-04-08T00:05:06.930 に答える
2

最後returnrunResourceT( http://hackage.haskell.org/package/resourcet-1.1.1/docs/Control-Monad-Trans-Resource.html#v:runResourceT ) に置き換えます。タイプが示すように、これは ResourceT を IO アクションに変えます。

于 2014-04-07T13:35:47.870 に答える