24 Apr 2024
Programmers hate deleting things; we’ve all felt that feeling in the pit our stomach when we realise
that thing we deleted was really deleted, and on the other hand the security of deleting some
unused code, safe in the knowledge that it’s still really there in version control. In the sphere of
databases, this terror of deleting things leads people to advocate soft deletion: instead of
really deleting a record, you add a field which marks the record as deleted, and you treat any
record marked in that way as if it were deleted. This is generally a bad idea, and there are a
number of better ways of ensuring access to old data.
08 Jul 2023
I’ve played around a little bit with Haskell, but the closest I’ve got to doing
something serious with it is writing a relational algebra
interpreter (which I did use to do some
homework for a databases class, so I guess that’s genuine practical success). I
thought it would be interesting to try and write something practical, and for
some reason I decided to write a redis clone. On the one
hand, redis provides data structures and various operations on them, we seems
right in Haskell’s wheelhouse. On the other, redis exposes these data structures
over a network connection, which is precisely the sort of messy IO Haskell
sweeps under a carpet (or monad). So it seems like an interesting option to
learn how Haskell might fare in the real world.
02 Mar 2023
Streams were one of the big features of post-8 Java, and they remain a very
convenient tool for applying transformations to collections. One limitation,
though, is that they’re not really extensible; you’re largely stuck with the
stream operations provided by the standard library. In Java 8, for example,
there was no takeWhile
operation. It is of course possible to write this
yourself, so you can do something like:
StreamUtils.takeWhile(Stream.of(1, 2, 3)
.map(x -> x + 1),
x -> x < 2);
The comparatively superficial problem with this is that custom stream operations
look very different from the stream methods, making them harder to read when
used as part of a stream pipeline The more fundamental problem is that they’re
fairly cumbersome to write; generally, the implementation involves creating a
new Stream
implementation which itself uses a new Spliterator
implementation, which wraps the Spliterator
from the source Stream
(for
instance, here is the implementation of takeWhile
from the protonpack
library).
Would it be possible to provide something with the ergonomics of streams, but
with more extensibility? I happened to run across the
transducist TypeScript library,
which suggests maybe a more extensible alternative to streams could be created
based on transducers.
01 Oct 2022
Why would you use the IO monad in Java? Well, the IO monad allows you to
represent side-effecting actions as values, separating IO from logic which you
can express as pure functions thereby…. Yes, yes, yes, but why would you use
the IO monad in Java? In languages like Haskell, the IO monad is the only way
to perform IO, so you can be certain any function that does not reference the IO
monad is a pure function; even Scala, which doesn’t prevent you from doing IO
outside of the IO monad, provides a number of useful tools for working with
monads. Java doesn’t provide either of these advantages, and indeed I doubt it’s
particular useful to use the IO monad in Java. But that doesn’t mean it’s not
interesting to implement the IO monad in Java. In surgery, there’s an adage that
to master a procedure, you “see one, do one, teach one”. Analogously, I’ve used
the IO monad when writing in Haskell and Scala, but I thought I might get a
deeper understanding by attempting to implement it; and I suppose by writing
this blog post explaining the implementation, I’m now completing the “teach one”
step (the reason for choosing to write the implementation in Java specfically
was that I was sketching out an approach to something in Java for work, when I
realised I would end up with half a buggy version of the IO monad, at which
point I scrapped the plan and went with something simpler; but it did get me
thinking).
19 May 2022
The SKI combinator calculus is a formal system which is one of the simpler
Turing-complete systems. Its building blocks are the three combinators S
, K
,
and I
. These are the atomic terms; other terms can be built by joining two
terms together.