简体   繁体   English

Haskell不评估区块

[英]Haskell does not evaluate block

I am writing simple sitemap.xml crawler. 我正在编写简单的sitemap.xml搜寻器。 The code is below. 代码如下。 My question is why the code in the end of main does not print anything. 我的问题是为什么main末尾的代码不打印任何内容。 I suspect it's because haskell's lazyness but don't know how to deal with it here: 我怀疑这是因为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

Substitute your last return with runResourceT ( http://hackage.haskell.org/package/resourcet-1.1.1/docs/Control-Monad-Trans-Resource.html#v:runResourceT ). runResourceThttp://hackage.haskell.org/package/resourcet-1.1.1/docs/Control-Monad-Trans-Resource.html#v:runResourceT )代替您的上一次return As it's type suggests, it would turn ResourceT into IO action. 顾名思义,它将把ResourceT变成IO动作。

You're running into the same problem I describe here, at least as far as having incorrect code that typechecks when it should actually give a type error: Why is the type of "Main.main", "IO ()" and not "IO a"? 您遇到了我在这里描述的相同问题,至少是因为有不正确的代码会在实际应提供类型错误时进行类型检查: 为什么类型为“ Main.main”,“ IO()”而不是“ IO一个”? . This is why you should always give main the type signature main :: IO () explicitly. 这就是为什么您应该始终为main类型签名main :: IO ()

To fix the problem, you will want to replace return with lift (see http://hackage.haskell.org/package/transformers/docs/Control-Monad-Trans-Class.html#v:lift ) and replace sequence $ map ... with mapM_ . 要解决此问题,您将需要用lift替换return (请参阅http://hackage.haskell.org/package/transformers/docs/Control-Monad-Trans-Class.html#v:lift )并替换sequence $ map ...使用mapM_ mapM_ f is equivalent to sequence_ . map f mapM_ f等效于sequence_ . map f sequence_ . map f . sequence_ . map f

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM