
I think the mistake here is to parse something and then decide if its it valid. It should be the parser which decides whether its valid. So rather than:
suffix <- A.option "" ((:"") <$> A.letter_ascii)
try:
typ <- A.choice [ {- list or valid suffix parsers -} ] return $ Score.Typed typ num
I actually had that originally, but but switched to fail-after for the better error msg. It worked with parsec, but then I lost it again when I switched to attoparsec. I think Wren is right, I really would need to refactor the parser to put the decisions in the right spot.
We you using Parsec as a token parser or as a Char parser. Obviously the second is going to be slow in comparison to the first.
It was actually the Text version of parsec, back when that was new. I should go do a profile again someday, but since attoparsec and parsec APIs are almost but not quite the same, it's kind of a pain. I actually tried the Text version of attoparsec, back when that was not yet integrated into attoparsec itself, and bytestring was still significantly faster. So I don't know how much was Text vs. ByteString and how much was parsec vs. attoparsec.