将一个ResumableSource附加到另一个

时间:2016-06-21 19:55:00

标签: haskell conduit

如果ResumableSource明确是Monad的实例,那么如何将a附加到另一个Monad?以下是一个玩具示例 - ba's约束,b's没有约束。因此,我们可以追加Prelude> import Data.Conduit Prelude Data.Conduit> import Data.ByteString as BS Prelude Data.Conduit BS> import Control.Monad.Trans.Resource Prelude Data.Conduit BS Control.Monad.Trans.Resource> let a = newResumableSource (yield (BS.pack [5])) -- this one has monad constraint Prelude Data.Conduit BS Control.Monad.Trans.Resource> :t a a :: Monad m => ResumableSource m ByteString Prelude Data.Conduit BS Control.Monad.Trans.Resource> :t a >> a a >> a :: (Monad m, Monad (ResumableSource m)) => ResumableSource m ByteString Prelude Data.Conduit BS Control.Monad.Trans.Resource> let b = undefined :: ResumableSource (ResourceT IO) ByteString Prelude Data.Conduit BS Control.Monad.Trans.Resource> :t b >> b <interactive>:1:3: No instance for (Monad (ResumableSource (ResourceT IO))) arising from a use of ‘>>’ In the expression: b >> b 但不能追加HTTP ResumableSource

b

我问的原因是因为我的responseBody rsp $$+- sink ((newResumableSource (yield content-len)) >> (responseBody rsp)) $$+- sink 上面的index.yaml相同,我希望在将其提供给接收器之前将其添加到内容长度之前。目前,它看起来像这样:

index.yaml

我想改成这样的事情:

gcloud beta emulators datastore start

1 个答案:

答案 0 :(得分:0)

将初始消息添加到ResumableSource的好方法似乎是使用conduit来生成该初始消息,然后成为传递。在这里,我借用了map管道中的代码来创建这样的管道:

passThruWInit :: Monad m => BS.ByteString -> C.Conduit BS.ByteString m BS.ByteString
passThruWInit initMsg = do
  C.yield initMsg -- generate initial message first
  C.awaitForever $ C.yield -- now pass-through conduit for all messages

现在,我们更新responseBody rsp $$+- sink代码以适应它们:

responseBody rsp $=+ passThruWInit someInitMsg $$+- sink

最终结果是首先产生someInitMsg,然后流式传输responseBody内容。这样,我们就可以将内容长度和其他元数据添加到可恢复的HTTP响应主体中。