http 管道中的 ResumableSource 导致 "Cannot construct an infinite type" 错误
ResumableSource in http conduit results in "Cannot construct an infinite type" error
我正在尝试创建一个函数,该函数在给定一些参数的情况下创建 Source 以连接到 URL,同时正确地位于 ResourceT monad 中。我正在尝试以下操作:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.IO.Class (liftIO)
import Data.Conduit (($$), yield, unwrapResumable)
import qualified Data.Conduit.List as CL
import Network.HTTP.Conduit
import Network.HTTP.Types (methodPost)
import Control.Monad.Trans.Resource (runResourceT)
runquery manager = do
initreq <- parseUrl "http://localhost/test"
let request = initreq{method=methodPost, requestBody=RequestBodyLBS "test"}
response <- http request manager
(httpsource, finalizer) <- unwrapResumable (responseBody response)
httpsource
finalizer
main = do
manager <- newManager conduitManagerSettings
runResourceT $ (runquery manager $$ CL.mapM_ (liftIO . print))
它不起作用,我从编译器收到 'cannot construct the infinite type' 错误。我可以 return (httpsource,finalizer)
(或只是整个 responseBody)并在以后使用它,但在我看来这很奇怪。编写此代码的正确方法是什么?为什么会出现无限类型错误?
没有类型签名,我得到以下错误:
test.hs:17:3:
Occurs check: cannot construct the infinite type:
m
~
conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString m
Expected type: m ()
Actual type: Source m ByteString
Relevant bindings include
finalizer :: m () (bound at test.hs:16:16)
httpsource :: Source m ByteString (bound at test.hs:16:4)
response :: Response
(conduit-1.2.4:Data.Conduit.Internal.Conduit.ResumableSource
m ByteString)
当我添加签名时,(我希望应该是):
runquery :: Manager -> Source (ResourceT IO) ByteString
我得到一个错误:
Couldn't match type ‘conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString (ResourceT IO)’
with ‘ResourceT IO’
Expected type: conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString (ResourceT IO) ()
Actual type: Source
(conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString (ResourceT IO))
ByteString
我可能正在做一些无法完成的事情,但我不太明白问题出在哪里。
unwrapResumable、http 和 finalizer 需要 运行 在 resourceT 中似乎只能在 MonadResource 上下文中工作(例如 resourceT),因此您必须将它们提升到其中。
runquery :: MonadResource m => Manager -> Source m ByteString
-- or runquery :: Manager -> Source (ResourceT IO) ByteString
runquery manager = do
initreq <- parseUrl "https://localhost/test"
let request = initreq{method=methodPost, requestBody=RequestBodyLBS "test"}
response <- lift $ http request manager
(httpsource, finalizer) <- lift $ unwrapResumable (responseBody response)
httpsource
lift finalizer
main :: IO ()
main = do
manager <- newManager conduitManagerSettings
runResourceT $ (runquery manager $$ CL.mapM_ (liftIO . print))
我正在尝试创建一个函数,该函数在给定一些参数的情况下创建 Source 以连接到 URL,同时正确地位于 ResourceT monad 中。我正在尝试以下操作:
{-# LANGUAGE OverloadedStrings #-}
import Control.Monad.IO.Class (liftIO)
import Data.Conduit (($$), yield, unwrapResumable)
import qualified Data.Conduit.List as CL
import Network.HTTP.Conduit
import Network.HTTP.Types (methodPost)
import Control.Monad.Trans.Resource (runResourceT)
runquery manager = do
initreq <- parseUrl "http://localhost/test"
let request = initreq{method=methodPost, requestBody=RequestBodyLBS "test"}
response <- http request manager
(httpsource, finalizer) <- unwrapResumable (responseBody response)
httpsource
finalizer
main = do
manager <- newManager conduitManagerSettings
runResourceT $ (runquery manager $$ CL.mapM_ (liftIO . print))
它不起作用,我从编译器收到 'cannot construct the infinite type' 错误。我可以 return (httpsource,finalizer)
(或只是整个 responseBody)并在以后使用它,但在我看来这很奇怪。编写此代码的正确方法是什么?为什么会出现无限类型错误?
没有类型签名,我得到以下错误:
test.hs:17:3:
Occurs check: cannot construct the infinite type:
m
~
conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString m
Expected type: m ()
Actual type: Source m ByteString
Relevant bindings include
finalizer :: m () (bound at test.hs:16:16)
httpsource :: Source m ByteString (bound at test.hs:16:4)
response :: Response
(conduit-1.2.4:Data.Conduit.Internal.Conduit.ResumableSource
m ByteString)
当我添加签名时,(我希望应该是):
runquery :: Manager -> Source (ResourceT IO) ByteString
我得到一个错误:
Couldn't match type ‘conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString (ResourceT IO)’
with ‘ResourceT IO’
Expected type: conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString (ResourceT IO) ()
Actual type: Source
(conduit-1.2.4:Data.Conduit.Internal.Conduit.ConduitM
() ByteString (ResourceT IO))
ByteString
我可能正在做一些无法完成的事情,但我不太明白问题出在哪里。
unwrapResumable、http 和 finalizer 需要 运行 在 resourceT 中似乎只能在 MonadResource 上下文中工作(例如 resourceT),因此您必须将它们提升到其中。
runquery :: MonadResource m => Manager -> Source m ByteString
-- or runquery :: Manager -> Source (ResourceT IO) ByteString
runquery manager = do
initreq <- parseUrl "https://localhost/test"
let request = initreq{method=methodPost, requestBody=RequestBodyLBS "test"}
response <- lift $ http request manager
(httpsource, finalizer) <- lift $ unwrapResumable (responseBody response)
httpsource
lift finalizer
main :: IO ()
main = do
manager <- newManager conduitManagerSettings
runResourceT $ (runquery manager $$ CL.mapM_ (liftIO . print))