Jeremy Bowers writes about Go, functional programming, Haskell, and software design, including a monad tutorial and a Go supervisor-tree library.
Commenters recommend his monad tutorial for people tired of tutorials, his functional programming lessons for imperative code, and a post on analyzing failures instead of blaming people.
> HN and the internet being what it is, I'm sure someone can pop up here with some horror story about when it happened to them, but I would contend that it's still something so unusual as to not be worth planning for. Maybe just a twinge in the gut if you really did declare an interface with just a Shoot of no parameters and no return value, but... if nothing else, in the Go world, the odds of you having a Camera.Shoot() and a Gun.Shoot() method are low anyhow, and the odds of them conflicting even lower. First you have to declare an interface that both of them fully implement. If you have a .Reload method on your gun, but not your camera, you can't accidentally cross them. If you have a .Reload method on both, but the Gun takes an Ammunition argument and the Camera takes a Film argument, they can't cross. And from a pure software-engineering perspective, you have to a have a program in which you are using the same exact word for two completely different concepts, which can happen, but is bad practice and still takes some work.
Depends how you're using your types. E.g. one pattern I often use is wrapping up a String as a type so that I don't confuse two different domain-specific Strings - so I'll have something like:
public class PhoneNumber {
final String value;
}
public class EmailAddress {
final String value;
}
(In Scala this is even easier, with @@)
This is a really useful distinction to draw (in many ways it's more important than when…
I was getting ready to post the exact same thing. The built in event loop is major. Go did a lot of modelling from Erlang, but made tradeoffs that kept it closer to a C-style programming model.
It's a great language and the limits of its concurrency model aren't something that will really be apparent to you if you haven't learned Erlang/Elixir. For most people, it provides a concurrency model that's a cut above everything else out there.
The main differences in Go and BEAM languages (Erlang/Elixir) are cooperative vs prescheduling, shared memory vs immutable message passing, general garbage collection vs heap per process, and lastly general runtime vs isolation.
Cooperative scheduling means that the scheduler has to have control relinquished back to it (such as with I/O events), while prescheduling will take back control. Cooperative means that you can get better end-to-end performance for a benchmark but you run the risk of a code taking over the processor. Prescheduling will allow consistent performance for all operations in the run time without allowing anything to overtake it. That's one of the ways that it's possible to reliably run a database within the runtime alongside the rest of your code on BEAM.
Shared memory with pointers is pretty standard and definitely provides some performance perks, especially when dealing with large data structures. The flip side means that native clustering doesn't work. With BEAM languages that lack shared memory and rely on message…
You started out by saying 99% of web code is IO, then casually dropped down to 70-80%, as if that was the same thing. 20-30% of a huge codebase is still a significant amount.
I've never said IO is irrelevant to web applications. But that in my experience, those 20-30% or whatever can be important, complex and time intensive (the Word generation was actually one od the most time consuming parts of the last application I worked on) enough that fencing them off from the side effecting code in some way can pay off (one way to do this without going fully PFP is outlined here: https://www.jerf.org/iri/post/2025/fp_lessons_purity/#fp-pure-core---imperative-purifiable-core).
> First one looks like meta programming. IO. You are programming something else.
I don't understand what you're saying. I was working on a document management system whose contents were stored in tree structures. These structures routinely had to be transformed into other structures. That's a very algorithmic task where the IO can be fenced off very easily (and should be fenced off if only for the sake of easier unit testing). This was literally one of the most common things happening in the codebase.
> Chatbots are high IO.
in the sense that every useful program has IO. Otherwise, there's a whole bunch of transformations and intent recognition and skill dispatch and what not that happens between the request and the response, and that can happen entirely in memory on one machine (it can also be offloaded…
In C# you can implement SelectMany for a type and that gives this:
from id in ParseId(inputId)
from user in FindUser(id)
from posts in FindPostsByUserId(id)
from res in DeactivateDecision(user, posts)
select res;
It is the equivalent to do-notation (was directly inspired by it). Here's an example from the language-ext Samples [1], it's a game of 21/pontoon.
> I wrote what you might call an acid test for monad implementations a while back: https://jerf.org/iri/post/2928/ It's phrased in terms of tutorials but it works for implementations as well; you should be able to transliterate the example into your monad implementation, and it ought to look at least halfway decent if it's going to be usable.
If I try to implement the test from your blog with Seq type in language-ext (using C#), then I get:
Seq<(int, string)> minimal(bool b) =>
from x in b ? Seq(1, 2) : Seq(3, 4)
from r in x % 2 == 0
? from y in Seq("a", "b")
select (x, y)
: from y in Seq("y", "z")
select (x, y)
select r;
It yields:
[(1, y), (1, z), (2, a), (2, b)]
[(3, y), (3, z), (4, a), (4, b)]
Which I think passes your test.
[1] https://github.com/louthy/language-ext/blob/main/Samples/CardGame/Game.cs
Idk, while system architecture diagrams look cool and feel informative, I generally don't feel like they actually help you get started working somewhere on a project. Mistake #3 in this article, putting too much in, is part of this.
So https://www.jerf.org/iri/post/2025/on_layers_and_boxes_and_lines/#diagrams-huh-what-are-they-good-for is an interesting take: put links in your diagram, so it functions as a table of contents. This seems most useful for someone who needs to start working on a project.
Similarly https://haskellforall.com/2026/02/browse-code-by-meaning asks how to show what's in a repo, but maybe file tree is not best and a diagram with links as table of contents is the answer.
That said practically speaking, I'm not sure what tooling easily creates working links in a diagram that looks good in any context, for instance mermaid might render on github but not a text editor.
Of course for other purposes maybe just go crazy with the diagram. I once had a coworker draw this super detailed master diagram, maybe 50-100 things on it, which I was told impressed senior government officials (after my manager recolored all the red to avoid connoting errors). But for the purpose of orienting developers a table of contents with links sounds better.
Having just now taken delivery of a new technical book - Learn You a Haskell for Great Good! - I'm guessing that rumors of their death, as Mark Twain said about his own, are greatly exaggerated. I bought it on the basis of an online review that would inform this discussion. http://www.jerf.org/iri/post/2910
In the review, Jeremy Bowers discusses his own experience trying to learn Haskell over the past few years from the random bits and pieces that float about the web and how the careful development of ideas in this book "blew what turned out to be my rickety assemblage of concepts apart and replaced them with a solid understanding of what is going on with them, and why."
We tend to forget that learning is not the same as carrying around a giant reference book. It's a painstakingly linear process where leaps of understanding happen only when a solid foundation is in place. Books and the linear style of books will always be with us, but to compete with instant search writers must learn to teach.