0

ResourceT モナドに正しく存在しながら、URL に接続するためのいくつかのパラメーターを指定して Source を作成する関数を作成しようとしています。私は次のことを試みています:

{-# 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))

機能しません。コンパイラから「無限型を構築できません」というエラーが表示されます。私は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

できないことをしているのかもしれませんが、どこに問題があるのか​​ よくわかりません。

4

1 に答える 1

0

unwrapResumable、http、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))
于 2015-04-30T15:51:55.330 に答える