Pipes.Binary.decode - StateT用于什么?

use*_*399 8 haskell haskell-pipes

我正在尝试使用管道和基于它构建的各种库来编写基本的网络服务器.预期的流程是:

从socket接收字节串 - >使用二进制解码 - >服务器逻辑在这里 - >发送响应到套接字

我认为这将是:

fromSocket s 4096 >-> decode >-> serverLogic >-> toSocket s
Run Code Online (Sandbox Code Playgroud)

管道二进制有一个decode和一个decodeMany,但我不确定我理解差异,我不知道如何使用decode.为什么decodeMany将上游管道作为参数而不是用它链接>->?你如何使用decode,StateT我的管道最终应该是什么样的?

J. *_*son 5

这个StateT (Producer a m r) m x成语来自于pipes-parse"低级解析者".它通常意味着库正在使用drawunDraw从中提取值,Producer如果它们未使用则返回它们.它是解析可能发生故障的重要组成部分.它还要求该StateT层指示管道被选择性地排出并以有状态的方式重新填充.

-- | Draw one element from the underlying Producer, 
-- returning Left if the Producer is empty
draw :: Monad m => StateT (Producer a m r) m (Either r a)

-- | Push back an element onto the underlying Producer
unDraw :: Monad m => a -> StateT (Producer a m r) m ()
Run Code Online (Sandbox Code Playgroud)

所以,这是什么意思为decodedecodeMany?如果我们看一些这些函数的简化类型

-- for (Monad m, Binary b)

decode     :: StateT (Producer ByteString m r) m (Maybe b)
decodeMany :: Producer ByteString m r 
           -> Producer' b m (Either (Producer ByteString m r) r)
Run Code Online (Sandbox Code Playgroud)

我们首先看到的decode是从一个有状态的drawing足够的ByteString块,Producer ByteString以便尝试解析一个b.由于ByteStrings 上的块边界可能与解析边界不对齐,StateT所以执行此操作非常重要,这样剩余的块就可以unDraw重新进入Producer.

decodeMany在atop上构建decode并尝试重复decode b关闭输入生产者在失败时返回Producer剩余ByteString的"延续" .

长话短说,由于需要unDraw剩余的ByteString块,我们可以将这些东西组合成一个链条(>->).如果你想这样做,你可以使用类似的东西decodeMany来转换生产者,然后链接结果,但你需要仔细处理错误情况.