我正在尝试创建一个管道,该管道将通过管道源从HTTP流式传输数据。这是我到目前为止的内容:
import qualified Network.HTTP.Client.Conduit as CC
getStream :: String -> IO (ConduitM () BS.ByteString IO ())
getStream url = do
req <- parseUrl url
return $ CC.withResponse req $ \res -> do
responseBody res $= (awaitForever $ \bytes -> liftIO $ do
putStrLn $ "Got " ++ show (BS.length bytes) ++ " but will ignore them")
但是我越来越
No instance for (Control.Monad.Reader.Class.MonadReader env0 IO) …
arising from a use of ‘CC.withResponse’
In the expression: CC.withResponse req
In the second argument of ‘($)’, namely
‘CC.withResponse req
$ \ res
-> do { responseBody res $= (awaitForever $ \ bytes -> ...) }’
In a stmt of a 'do' block:
return
$ CC.withResponse req
$ \ res
-> do { responseBody res $= (awaitForever $ \ bytes -> ...) }
MonadReader
预期如何?这对我来说没有任何意义。
Network.HTTP.Conduit docs中的示例如何变化:
{-# LANGUAGE OverloadedStrings #-}
module Lib2 () where
import Data.Conduit (($$+-), awaitForever)
import qualified Network.HTTP.Client.Conduit as CC
import Network.HTTP.Conduit (http, tlsManagerSettings, newManager)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Resource (runResourceT)
import Data.Conduit.Binary (sinkFile) -- Exported from the package conduit-extra
main2 :: IO ()
main2 = do
request <- CC.parseUrl "http://google.com/"
manager <- newManager tlsManagerSettings
runResourceT $ do
response <- http request manager
CC.responseBody response $$+- (awaitForever $ \x -> liftIO $ putStrLn "Chunk")
原始答案
的返回类型getStream
错误。尝试删除类型签名并使用FlexibleContexts
,例如:
{-# LANGUAGE OverloadedStrings, FlexibleContexts #-}
module Lib () where
import Data.Conduit
import qualified Data.ByteString as BS
import qualified Network.HTTP.Client.Conduit as CC
import Control.Monad.IO.Class
getStream url = do
req <- CC.parseUrl url
CC.withResponse req $ \res -> do
CC.responseBody res $= (awaitForever $ \x -> liftIO $ putStrLn "Got a chunk")
然后:t getStream
报告:
getStream
:: (monad-control-1.0.0.4:Control.Monad.Trans.Control.MonadBaseControl
IO (ConduitM a c m),
mtl-2.2.1:Control.Monad.Reader.Class.MonadReader env m, MonadIO m,
CC.HasHttpManager env,
exceptions-0.8.0.2:Control.Monad.Catch.MonadThrow m) =>
String -> ConduitM a c m ()
这表明返回类型的格式为ConduitM ...
,而不是IO ...
。
这也说明了如何MonadReader
进入图片。monadm
必须能够通过读取器环境访问HTTP管理器,如以下约束所示:
CC.HasHttpManager env
MonadReader env m
这就是说,它m
具有某种类型的阅读器环境,该阅读器环境env
本身具有访问HTTP管理器的方式。
特别地,m
不能只是普通的IO
monad,这就是错误消息所抱怨的。
在评论中回答问题
这是如何Producer
从HTTP响应中创建一个示例:
{-# LANGUAGE OverloadedStrings #-}
module Lib3 () where
import qualified Data.ByteString as BS
import qualified Network.HTTP.Client.Conduit as CC
import Network.HTTP.Conduit (http, tlsManagerSettings, newManager)
import qualified Network.HTTP.Client as Client (httpLbs, responseOpen, responseClose)
import Data.Conduit (Producer, addCleanup)
import Data.Conduit (awaitForever, await, ($$))
import qualified Network.HTTP.Client.Conduit as HCC
import Control.Monad.IO.Class (liftIO, MonadIO)
getStream url = do
request <- CC.parseUrl url
manager <- newManager tlsManagerSettings
response <- Client.responseOpen request manager
let producer :: Producer IO BS.ByteString
producer = HCC.bodyReaderSource $ CC.responseBody response
cleanup _ = do liftIO $ putStrLn "(cleaning up)"; Client.responseClose response
producerWithCleanup = addCleanup cleanup producer
return $ response { CC.responseBody = producerWithCleanup }
test = do
res <- getStream "http://google.com"
let producer = CC.responseBody res
consumer = awaitForever $ \_ -> liftIO $ putStrLn "Got a chunk"
producer $$ consumer
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句