Haskell Language Combinators


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 ':')
  return $ Day name

To parse the time portion we could write:

data TimePortion = TimePortion String String

time = do
    start <- takeWhile1 isDigit
    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"