2016-03-21 12 views
4

私はハスケルにとっては新しく、最初のプロジェクトは捕捉されたWLANパケットを解析することです。そのようなパケットを解析する際の共通のパターンは、ヘッダフィールドが残りのバイトの構造を定義することである。ヘッダ内のフラグフィールドは、(ビットマップであることができる)パケットに含まれるものペイロード(複数可)を指定ハスケルでのバイナリデータのモナド解析

header + [payload A | payload B | ..] 

:一般的な例として、パケットは次のようにフォーマットすることができます。このフォーマットの具体例については、radiotapをご覧ください。ペイロードABの存在がヘッダで定義されている私の場合には適用できないと思われるしかし

parseAll = do 
    hdr <- parseHeader 
    pa <- parsePayloadA 
    pb <- parsePayloadB 

A similar threadはちょうどこのようparse一連の操作を使用することを示唆しています。換言すれば、データ解析の制御フローは、前の解析結果に従う必要がある。この種のパターンでバイナリデータを解析する一般的な方法があるのであれば、私は理解したいと思いますか?

答えて

2

注(do表記とバインドの使用からもわかるように)。モナドの力は、parsePayloadAparsePayloadBのあなたの選択がhdrに依存する可能性があります。あなたはHaskellのフルパワーを持ってhdrを調べることができます。与え、

(>>=) :: m a -> (a -> m b) -> m b 

a -> m bの矢印は、実際のHaskellの関数矢印である:だから、基本的にあなたがモナドバインドのタイプであるためあなたが特にこの力を持っている

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) 

ような何かを行うことができます

あなたが必要とするすべての力。

+0

ありがとうございました。この場合、「ペイロード」のタイプは何でしょうか? – liu3tao

+0

これは、2つの可能なペイロードを持っていると仮定しています。 'data Payload = PayloadA A |ペイロードB B – Cactus

1

これはMonadインタフェースの目的であり、前の計算の結果に対する計算の依存性をエンコードすることです。

あなたのケースでは、以下のようなものになるでしょう:

あなたの目的のために
parseAll = do 
    shouldThePayloadABeParsed <- parseHeader 
    if shouldThePayloadABeParsed 
    then do 
     pa <- parsePayloadA 
     ... 
    else do 
     pb <- parsePayloadB 
     ... 

私はどのようにHaskellで作品を解析し、この種の、および"binary-parser"パッケージの理解を得るために"Taste of State: Parsers are Easy"記事を読んお勧めします解析を行う。 parseAllモナドパーサーライブラリのいくつかの種類を使用すること