Haskell and SQLite for the win, starring corecursion
We learn how to make a side project low maintenance with clever use of boring technology. We also get an aimless look at how to achieve corecursion with foldr.
Hello! I hope your week is going well.
New articles
Single-File Stateful Haskell Web App
I have avoided stateful side projects for over six years, but Decision Drill is a stateful side project. How can one approach that without accidentally promising perfect data integrity forever? How can one implement it so the maintenance demands are low?
I don't actually know, but I think Haskell, SQLite, and explicitly limited retention are a good start.
Full article (5–12 minute read): Single-File Stateful Haskell Web App
Flashcard of the week
I wasn't quite sure what to pick this week, so I picked something that triggers a little "aha" in my head every time I get it right, and then I promptly forget again.
What is required of an operation passed to foldr for the fold to be corecursive?
Corecursion means two functions calling each other, but here it is used in a slightly different sense: functions that operate on streams (or generators, in Python speak) are also considered corecursive, because they hand control back to the caller between each generated element.
The operation must yield a data constructor that is lazy in its second argument.
This is specific to Haskell and other lazy languages, but as soon as a function produces a data constructor, control is passed back to the caller – the arguments passed into the constructor do not, by default, get evaluated.
That's sort of one half of what laziness is: we can construct objects without evaluating the constructor arguments.
(The second half is constructing function calls without evaluating them, but even in lazy code, pattern matches happen often enough, and they evaluate function calls but leave constructor arguments unevaluated, so as a first approximation, we can think of just constructor arguments as unevaluated.)
In a very dumb example, we can do
> foldr (\x xs -> negate x : xs) [] [1, 2, 3]
[-1, -2, -3]
but we can also do
> foldr (\x xs -> negate x : xs) [] [1..]
[-1, -2, -3, -4, -5, -6, -7,^CInterrupted.
and this produces an infinite stream of negative numbers, one at a time, because with this operation foldr is corecursive. On the first iteration, it will yield the (unapplied) data constructor
negate 1 : foldr (\x xs -> negate x : xs) [] [2..]
and when we try to get the first value from that list, it will get evaluated down to
-1 : foldr (\x xs -> negate x : xs) [] [2..]
and at this point it's possible to get the first value of that list, without having to evaluate any subsequent values, because the : operator is lazy in its second argument. If we force the operation to be strict in its second argument with a strictness annotation, we won't get anything because the computation never finishes:
foldr (\x !xs -> negate x : xs) [] [1..]
Here, the strict second argument to the operation means foldr is no longer corecursive. With this strictness annotation, it is impossible for the list to be in the intermediary state
-1 : foldr (\x !xs -> negate x : xs) [] [2..]
that we had before, because the operation now evaluates the right-hand side before yielding its data constructor. And the right hand side is in turn not corecursive, since it has the same strictness annotation on the operation.
I'm not exactly sure where I'm going with this but it's neat to start to get some sort of intuition for what laziness is more practically. It is needed surprisingly rarely when working with production Haskell, but when it is needed – oh dear is it needed!
Premium newsletter
The new premium newsletter went out yesterday!
It had a preview of a future article, a review of Code That Fits In Your Head, links to two of my favourite text adventures you can play for free, and a few more web links. To get access to it, a premium subscription is currently only $2/month, cancelable at any time, no questions asked.
That money also gets you the past issues, which total five longer book reviews/summaries, 22 brief book recommendations, forecasting/world modeling tips, and around 12 great web links.
To upgrade, click the subscription link at the top of this newsletter and fill in your email again.
Your opinions
I cannot improve without feedback. Reply to this email to share your thoughts on any of the topics above, or anything else!Hello! I hope your week is going well.