如果ResumableSource
明确是Monad
的实例,那么如何将a
附加到另一个Monad
?以下是一个玩具示例 - b
有a'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
答案 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响应主体中。