通过haskell管道管道http流

假龙

我正在尝试创建一个管道,该管道将通过管道源从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不能只是普通的IOmonad,这就是错误消息所抱怨的。

在评论中回答问题

这是如何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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章