Genuinely curious on the types of projects you use Haskell for! I’ve been thinking of learning it beyond the lightweight treatment I got during my CS degree.
Mostly “boring” stuff where the type system pays rent fast:
- Domain/state machines (payments/fulfillment-style workflows): modeling states + transitions so “impossible” states literally can’t be represented.
- Parsers/DSLs & config tooling: log parsers, small interpreters, schema validation, migration planners.
- Internal CLIs / automation: batch jobs, release helpers, data shapers, anything you want to be correct and easy to refactor later.
- Small backend services when the domain is gnarly (Servant / Yesod style) rather than huge monoliths.
If you’re learning it beyond CS exposure, I’d start with a CLI + a parser (JSON/CSV/logs), then add property-based tests (QuickCheck). That combo teaches types, purity, effects, and testing in one project without needing to “go full web stack” on day 1.
Resumable code is extremely helpful and I'm pretty sure you're describing a chicken and egg issue: if resumable code was readily available in general, people would use it a lot more and it would look like a very normal tool that is often the best.
But when it's only a feature available in niche languages or many languages make it unsafe or unreliable, then very few people will get to the point where it naturally pops up in their mind as a solution to their problem.
This is basically what we already have in Haskell. Debug functions that sidestep the typing system can be annotated with a warning and you can make this one an error while compiling for production.
And in a more general sense, you can ask the compiler to forbid escape hatches altogether.
First, you can write a function that's generic on the effects used, so you could write use it in a way that calls an LLM and use it elsewhere in a way that cannot, with the same logic.
But I see the need to change the code as a good thing when it is necessary: I don't want a dependency, inside or outside my codebase, to suddenly add network calls without me knowing it. Same goes for code that was pure and has become stateful. Not knowing this kind of fundamental change is a recipe for a nightmare.
It should be especially apparent with the recent supply chain attacks.
In the real world you usually want to extend datatypes and provide new implementations without recompiling let alone rewriting old code (The so called expression problem). This is the raison d'être of complex DI and IoC enterprise patterns and various monkey patching techniques.
I am not sure how flexible the effect approach is. It took decades before static typing became painless enough for rapid agile development. Properly typed DI with safeguards sounds wonderful, but can algebraic effects actually deliver that?
One typical way to resolve this is to use Voluntary Oblivious Compliance (VOC). In this capability-based pattern, every storage service could provide an opaque handler to a user that represents their authorization and it can be used to restrict on which documents indexing is done.
If the opaque handle is part of the Membrane pattern, you can even avoid most race conditions, because even during the indexing, the capabilities can be used to access documents and that removes the possibility of a TOCTOU race.
My team builds frontends in Elm and backends in Haskell and we experience the opposite: FP made the code very easy to reason about and plugging things together is easy too.
Most so-called software engineers fail to do something crucial in engineering: they have zero knowledge about the scientific state of the art about programming.
I agree that the absence of liability enables this.
That is interesting: yes, it is true. That's why you see these endless (poor) re-inventions of the wheel. If the state of the art would at least be commonly known and well communicated we could avoid some of that. Not all of it because another mantra is that re-inventing something (poorly) is a useful exercise. I agree with that on principle if you then end up using the blessed version in your actual work but more often than not it is the homebrew and rickety version that the whole house of cards will then end up depending on.
Experimenting around the state of the art or reimplementing the state of the art ourselves while being informed by it would be fine. I guess it would be a great exercise, as you said.