
Andrew Coppin wrote:
OK, well I don't know the Parsec types and function names off the top of my head, but suppose I have the following:
runParser :: Parser a b -> [a] -> Either ParseError b
parseHuffmanTable :: [x] -> Parser Word8 (HuffmanTable x)
parseHuffmanPayload :: HuffmanTable x -> Parser Word8 [x]
parseRLE :: Parser Word8 [Word8]
Now, if I want to just do without the RLE bit, I can do
parseHuffman :: [x] -> Parser Word8 x parseHuffman xs = do table <- parseHuffmanTable xs parseHuffmanPayload table
But if I want to add an RLE layer to just the Huffman table... erm... OK, I'm stuck now. :-S
1. How do I run the input through parseRLE and *then* through parseHuffmanTable?
2. How do I get parseHuffmanPayload to continue from where parseRLE left off? (How do I get parseRLE to not parse the entire input, for that matter...)
Well, there's no way to do that with a monolithic parseRLE since it will parse the input to the bitter end. But assuming that parseRLE = concat `liftM` many parseRLEBlock parseRLEBlock :: Parser Word8 [Word8] you can write an RLE parser that repeatedly parses RLE blocks until it has read equal or more than n Word8s parseRLEAmount n | n <= 0 = return [] | otherwise = do xs <- parseRLEBlock xss <- parseRLEAmount (n - length xs) return (xs ++ xss) To parse a huffman table, run the actual parser on the result of parseRLEAmount: parseHuffmanHeader = runParser parseHuffmanTable `liftM` parseRLEAmount (2^8) Regards, apfelmus