We recently refactored some gnarly code that manipulated customer and order records in our enterprise resource planning (ERP) system. That system had a few idiosyncrasies which complicated this task: Creating new records required referencing other entities by internal ID, so we had to do a number of lookups before issuing “create record” requests; For some entity types, we found it easiest to issue “search” API calls and extract the required IDs from the returned search results. This necessitated an extra parsing step between “we have a successful response” and “we have the ID we’re looking for”; and Requests are often slow, but the marginal cost of additional requests in a batch was quite low. This meant that we could expect some good results from batching related requests together. The benefits of batching led us to seek a solution that permitted static analysis. Applicative functors have a completely static control flow, and cannot express computations where one step depends on the result of a previous step. A well-chosen applicative would let us analyse the requests we need to send without executing any of them, batch queries together without worrying about data dependencies, and then route relevant results to each individual query to parse (if necessary). Our library users could ignore batching details but still gain the efficiency benefits of a batch query API. In this post, we’ll look how we’ve been using handles, what “free structures” are, how free applicatives elegantly solved some of our problems interfacing with a remote system, and how they interacted especially well with the “handle pattern”. Handles, as Bellroy uses them The “handle pattern” is a Haskell idiom that is similar to dependency injection in mainstream languages. Instead of directly writing in the side effects we want our code to perform, we accept a record of functions that we call a “handle”. (In an object-oriented language, we’d probably accept an object that implements an abstract inter...
First seen: 2025-10-16 04:45
Last seen: 2025-10-16 16:49