处理Streaming库中的sum编码

时间:2018-03-11 20:54:27

标签: haskell haskell-pipes haskell-streaming

这个问题背后的动机是这个场景 - 我们有一个由Sum编码表示的值流。让我们假设Either ByteString ByteString我们分别表示错误和良好状态的字节流。现在,我们有另一个可以压缩ByteString流的函数。是否可以在Either ByteString ByteString输入流上运行此功能,并在Right取代而不是Left时压缩其中一个(不仅仅是Left而且还有Right })。下面是compress函数类型签名(我正在使用Streaming库):

compress ::  MonadIO m 
         =>  Int 
         -- ^ Compression level.
         -> Stream (Of ByteString) m r
         -> Stream (Of ByteString) m r 

我们的输入流属于Stream (Of (Either ByteString ByteString)) m r类型。那么,是否有某种变换器函数可以在输入流上运行compress,并输出类型为Stream (Of (Either ByteString ByteString)) m r的流,两者都被压缩。

在我看来,我应该写一个自定义compress,让我们说eitherCompress如下:

eitherCompress :: MonadIO m 
             =>  Int 
             -- ^ Compression level.
             -> Stream (Of (Either ByteString ByteString)) m r
             -> Stream (Of (Either ByteString ByteString)) m r 

这是对的吗?如果是这种情况,使用zstd库中的以下函数编写eitherCompress的好方法是什么:

compress :: Int 
         -- ^ Compression level. Must be >= 1 and <= maxCLevel.
         -> IO Result    

我使用stream编写了yield个生成器,但我已经针对输入只是源而不是流的简单情况实现了它们。非常感谢帮助解决这个问题。

1 个答案:

答案 0 :(得分:2)

解决这些情况的一个常见技巧是将总和的每个分支放在不同的monadic层(因此将有两个流层)分别操作每个层,然后单独使用它们或者将它们重新连接到一个层中层

首先,使用maps转换为Sum仿函数组合的两个辅助函数:

toSum :: Monad m 
      => Stream (Of (Either ByteString ByteString)) m r 
      -> Stream (Sum (Of ByteString) (Of ByteString)) m r
toSum = maps $ \(eitherBytes :> x) -> 
    case eitherBytes of
        Left bytes -> InL (bytes :> x)
        Right bytes -> InR (bytes :> x)

fromSum :: Monad m 
        => Stream (Sum (Of ByteString) (Of ByteString)) m r 
        -> Stream (Of (Either ByteString ByteString)) m r
fromSum = maps $ \eitherBytes ->
    case eitherBytes of
        InL (bytes :> x) -> Left bytes :> x
        InR (bytes :> x) -> Right bytes :> x

我们这样做是为了能够使用separateunseparate函数。

实际的压缩功能是:

eitherCompress :: MonadIO m 
               => Int 
               -> Stream (Of (Either ByteString ByteString)) m r 
               -> Stream (Of (Either ByteString ByteString)) m r
eitherCompress level =
     fromSum . unseparate . hoist (compress level) . compress level . separate . toSum

hoist用于处理最顶层下面的monadic层。