[Haskell-cafe] Re: Abstraction leak

apfelmus apfelmus at quantentunnel.de
Sun Jul 1 09:12:56 EDT 2007


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



More information about the Haskell-Cafe mailing list