Today, I encountered a fun bug where f"{x}" threw a TypeError, but str(x) worked. Join me on my journey unravelling what f-strings do and uncovering the mystery of why an object might not be what it seems.
At LeapYear, we had a system of cross-references that turned out to be pretty handy. One common situation was if we wrote a comment explaining a complicated piece of logic and we want to "link" back to that comment at various parts of the code, but we want to make sure that "link" doesn't get broken in the future.
This work involved a lot of refactoring to how strings were lexed in GHC, with a lot of tricky spots with performance, considering how ubiquitous string literals are in Haskell programs. In this blog post, I will outline a few interesting takeaways from this experience.
The previous post discussed a design pattern that enables writing tests with stubbed responses to test complex IO functions. You might have read the post and were reminded of the blog post "Why mocking is a bad idea" and wondered why I'd be recommending such tests. Yes, I also agree that mocking is a bad idea; the difference is that the previous blog post discussed tests that stubbed IO actions, not mocked.
In large systems, dependency injection is a powerful design pattern that allows subsystems to be modular and iterate independently of other subsystems. Concretely, it enables building subsystems in parallel and testing them independently.
Most people know about the DRY concept; some people are also familiar with the dangers of DRY. Matt Rickard's blog post "DRY Considered Harmful" contains this particularly pithy quote:
I just released a new library tasty-autocollect, which aims to solve a lot of minor annoyances I've had with tasty-discover. I won't be going into too much detail about what it does (see the README instead), but I wanted to quickly go over some of the technical hurdles in implementing the library, and what I learned in this process.
One of my very first PRs into Fourmolu was setting up CI. Initially, I used Circle CI, as it's what I've used in all my other open source repos, and Matt Parsons initially expressed a slight preference to it over GitHub Actions. But as I've gotten more familiar with GitHub Actions, and also as I've been trying to figure out how to automate GitHub releases, it seems like the tighter out-of-the-box integration between the CI and GitHub makes our lives a bit easier.
Do you like YAML's relative readability but dislike all the ways a user could shoot themselves in the foot? If you're like me, you probably agree that it's not the user's job to remember that the file format they're using automatically converts true, on, yes, or y to a boolean TRUE[1]. In other words, the semantics of the token true is not inherent to that token, but is determined by the field you're currently configuring.
I'm implementing a GraphQL backend for my personal project in Typescript because that's where all the best GraphQL libraries are. Currently, I'm using apollo-server built on top of the graphql-js library, which I've been able to get working fine. But I often find myself wishing I could implement it in Haskell.
In my aeson-schemas library, I implement quasiquoters that will generate Template Haskell to define type-level schemas and operations to extract data out of a JSON object. Then I would write tests that look like this: