Haskell管道:如何在生成monadic值时向下游发送数据

时间:2016-07-10 03:29:38

标签: haskell conduit

我想编写一个代理,它会收到一个标题,指示目标IP,端口等。

所以我有这样的事情:

getHeader = do
    Just x <- await
    let (a, rest) = splitAt headerLen x
    return $ parseHeader a
    -- how to send the rest data downstream ??

(resume, header) <- clientSource $$+ getHeader
-- do something according to the header

问题在于,有时会将标头和后续数据一起发送,因此getHeader会消耗后续数据,这些数据应该被后来的管道消耗。那么如何发送rest下游?

1 个答案:

答案 0 :(得分:1)

您还可以考虑使用包含在管道中的解析器,例如 conduit-extra 中的Data.Conduit.Attoparsec。包装器负责根据需要请求尽可能多的输入部分(在您的情况下,可能会发生第一部分短于headerLen),以及处理剩余物:

import Control.Monad.Catch
import qualified Data.Attoparsec.ByteString as P
import Data.Attoparsec.Types
import qualified Data.ByteString as BS
import Data.Conduit
import Data.Conduit.Attoparsec


parseHeader :: Parser BS.ByteString BS.ByteString
parseHeader = P.take headerLen -- do whatever parsing you need to get the header
  where 
    headerLen = 42

consumerHeader :: (MonadThrow m) => Consumer BS.ByteString m BS.ByteString
consumerHeader = sinkParser parseHeader

Consumer定义为

type Consumer i m r = forall o. ConduitM i o m r

所以consumerHeaderByteString作为输入,在输出和monad中是多态的,并返回已解析的ByteString