Search code examples
parsinghaskellparsec

Partitioning different types of terms during parsing


I have two parsers for different types of terms.

a :: Parser A
b :: Parser B

I have a data type representing sequences of these terms.

data C = C [A] [B]

If my input is a sequence of mixed terms, what’s a good way of writing c :: Parser C to separate the As from the Bs, preserving their order? For example, given these definitions:

data A = A Char
data B = B Char
a = A <$> oneOf "Aa"
b = B <$> oneOf "Bb"

"abAbBBA" would parse to the sequences aAA and bbBB. I have a feeling I need to use StateT, but am unsure of the specifics and just need a push in the right direction.


Solution

  • A simple solution is to first parse it to a list of Either A B and then use partitionEithers to split this into two lists which you then apply the C constructor to.

    c :: Parser C
    c = uncurry C . partitionEithers <$> many ((Left <$> a) <|> (Right <$> b))