在Haskell中对二进制数据进行Monadic解析

liu*_*tao 5 monads haskell

我是Haskell的新手,我的第一个项目是解析捕获的WLAN数据包.解析这种分组的一种常见模式是头字段将定义剩余字节的结构.作为一般示例,数据包的格式如下:

header + [payload A | payload B | ..] 
Run Code Online (Sandbox Code Playgroud)

其中标头中的标志字段(可以是位图)指定包中包括哪些有效载荷.有关此格式的具体示例,请查看radiotap.

类似的线程建议只使用这样的一系列parse操作:

parseAll = do
    hdr <- parseHeader
    pa <- parsePayloadA
    pb <- parsePayloadB
Run Code Online (Sandbox Code Playgroud)

然而,似乎不能在我的情况下应用有效载荷的存在A并且B由头部定义.换句话说,数据解析的控制流程需要遵循先前的解析结果.我想明白,如果有一种通用的方法来解析这种模式的二进制数据?

Cac*_*tus 3

请注意,parseAll使用某种单子do解析器库(从符号和绑定的使用可以看出)。monad 的力量正是您的选择parsePayloadAparsePayloadB可以依赖的hdr:您拥有 Haskell 的全部力量来检查hdr

所以基本上你可以做类似的事情

parseAll = do
    hdr <- parseHeader
    payload <- case somethingInTheHdr hdr of
       ThisIsAnA -> do
         a <- parsePayloadA
         return (PayloadA a)
       ThisIsAB -> do
         b <- parsePayloadB
         return (PayloadB b)
    -- can use body here, e.g.
    return (Packet hdr payload)
Run Code Online (Sandbox Code Playgroud)

您之所以拥有这种能力,是因为在单子绑定类型中:

(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)

中的箭头a -> m b是真正的 Haskell 函数箭头,为您提供所需的所有功能。