In the last three episodes of Point-Free we explored the compositional properties of parsers by defining map
, flatMap
and zip
operations on them. Each operation carried with it precise semantic meaning, and that meaning is shared with many other types such as arrays, optionals, results, promises and more, and each one was a little more powerful than the last.
With those three operations we were able to cook up complex parsers by piecing together lots of tiny, easy-to-understand parsers. The example we developed was that of a latitude/longitude coordinate parser, which was built from many small parsers. But even though these three operations pack a punch, there are still some things that they cannot accomplish. For example, we cannot currently parse any number of values from some input string, like say a string that has a bunch of coordinates that are separated by newlines. Nor can we attempt to run a bunch of parsers against an input string till one succeeds, say if we support more than one format for a data type. Doing so with map
, flatMap
, and zip
alone is just not possible, so we need to figure out a way to take our parsers to the next level.
The key to this leveling up is none other than functions. Just plain functions. It’s an idea we’ve seen time and time again on Point-Free. By using functions that return parsers as output, or even better, take parsers as input and return parsers as output, we will unlock a whole new world of possibilities with our parsers. These functions are called “parser combinators”, but they could maybe even be called “higher-order parsers” to draw an analogy with “higher-order functions”.