Fluently Zipping Parsers

Episode #123 • Nov 2, 2020 • Subscriber-Only

The zip function shows up on many types: from Swift arrays and Combine publishers, to optionals, results, and even parsers! But zip on parsers is a little unlike zip on all of those other types. Let’s explore why and how to fix it.

Fluently Zipping Parsers
Introduction
00:05
The problem with zip
02:44
Solving with more overloads
10:45
Fluent parsers
16:20
Zipping from void
36:09
What’s the point?
44:45

Unlock This Episode

Our Free plan includes 1 subscriber-only episode of your choice, plus weekly updates from our newsletter.

Introduction

Last week we concluded our recap of parsers to bring everyone up to speed on what a parser is, how functional programming defines parsers, and how to decompose a large, complex problem into many small pieces. Today we’ll begin talking about some new topics, starting with how to provide a better interface to the zip function on parsers.

Recall that zip is a parser combinator whose job is to allow you to run many parsers on an input string. Each parser can consume a bit of the input string to produce a value of some first class data type, and once all the zipped parsers have run it delivers a tuple of all those values to you.

We’ve used the zip function quite a bit already. It’s probably one of the most important tools for building up complex parsers from simpler ones. And interestingly, the idea of “zipping” is not unique to parsing, there are a lot of data structures out there that support zip-like operations. First of all, probably most widely known, the Swift standard library comes with a zip defined on collections, but we’ve seen it also makes sense to define zip on optionals, results, random number generators, asynchronous values, Combine publishers, and more.

However, there is one thing about zipping parsers that’s a little different from all of those other examples. When parsing we are often consuming a bit from the input string and then completely discarding the result of that parsing. That is, the parser wants to consume some of the input but it doesn’t produce anything of interest to the user of the parser. For example, we’ve many times parsed a literal string off the front of the input, such as consuming a comma or a space, but those parsers only produce a Void value, hence nothing significant.

This is pretty unique to parsers. We aren’t often dealing with arrays of void values, or random generators of void values, or even asynchronous void values, but for parsers it is legitimately useful to have a void parser, and even quite common. And because of this oddity, our usages of zip when plugging together many parsers looked a little strange.

So, we are going to take another look at the zip function on parsers and see if we can come up with another formulation of zip that is a little friendlier to parsers. We will discover an API that not only fixes the problem we just described, but is also more fluent in the way it reads, and even requires us to have fewer overloads to handle the kinds of parsers we have been working with so far.

This episode is for subscribers only.

Subscribe to Point-Free

Access this episode, plus all past and future episodes when you become a subscriber.

See plans and pricing

Already a subscriber? Log in

Downloads