Parsing input is best achieved through larger parser functions that are composed of smaller, single purpose ones.
Let's say we wished to parse the following text which represents working hours:
Monday: 0800 1600.
We could split these into two "tokens": the day name -- "Monday" -- and a time portion "0800" to "1600".
To parse a day name, we could write the following:
data Day = Day String day :: Parser Day day = do name <- takeWhile1 (/= ':') skipMany1 (char ':') skipSpace return $ Day name
To parse the time portion we could write:
data TimePortion = TimePortion String String time = do start <- takeWhile1 isDigit skipSpace end <- takeWhile1 isDigit return $ TimePortion start end
Now we have two parsers for our individual parts of the text, we can combine these in a "larger" parser to read an entire day's working hours:
data WorkPeriod = WorkPeriod Day TimePortion work = do d <- day t <- time return $ WorkPeriod d t
and then run the parser:
parseOnly work "Monday: 0800 1600"