But I'm not a zealot. It's fun in the right domain.
But I'm not a zealot. It's fun in the right domain.
When those things come from a stream of business problems, Haskell, I hate to say, is a poor tool, for just the reason you stated. You’ll always come across situations where mutating state would make an incremental change very easy (despite being “bad practice” for long-term complexity) but where having rigorously designed a functional system, that mutation or change is now painfully hard and requires significant refactoring.
Because business pressures utterly do not care about engineering properties of the backend system, except for high level summaries of basic properties like overall cost or reliability (metrics that functional programming vs other paradigms doesn’t have much impact on), you end up never being able to justify the upkeep and refactor-as-you-go workloads necessary for the functional implementation to not get bastardized into the exact same sort of spaghetti code mess you get with other languages.
In my experience, the types of errors, bugs and extensibility headaches in a business setting are not addressable with static typing, designs leveraging a type system, formal verification, or immutable design patterns. Those things are fine, not knocking them. It’s just that they cannot help you for dealing with reactive business problems. They don’t live up to the hype about it.
The problems are all about a sudden context change in which a previously valid set of behaviors, performance characteristics, whatever, is instantly rendered invalid because circumstances have suddenly changed, and you need to simply react to it and pray you’re successful enough that the system even lives to some magical future time when you can refactor.
That's not to say that statically typed FP can't be written in such a way to allow this kind of arbitrary modification, but then you get into the realm of finding the perfect abstraction in the type system, which is exactly the same kind of maintenance problem that OO architecture astronauts bring to a code base.
This is all to say -- we should be writing Clojure, which allows a tight focus on actual business requirements while still being flexible enough to allow you to bail out of FP patterns when necessary. :)
In the Haskell systems I write, this change would be trivial. It’s a single line change. Maybe it’s just a benefit of the particular pattern I’m using (standard Yesod handler, which if I remember correctly is just the ReaderT IO pattern), but still, it seems completely wild in my view to trash an entire language and indeed an entire paradigm because you can’t imagine making the change in your example.
Regardless, the point is not that it's impossible to make such a change in a Haskell code base, just that it may or may not require non-trivial breaking changes, while such a change in an OO enterprise code base will always be trivial.
There's lots and lots wrong with OO patterns, but being able to respond to changing and arbitrary whacky business requirements is a clear strength.
Why? From where did you invent this completely arbitrary constraint?
> You shouldn't be putting business logic in your HTTP handlers.
Why not? How else could this work? The user has to interface with the business logic somehow.
There’s nothing at all wrong with a HTTP handler that takes in a request, delegates to a few different business logic things, and then sends a response.
Not only are you moving the goalposts with your argument, you’re also coming up with things that are completely false.
There’s nothing about OOP that inherently makes extending some code to send an email easy. Likewise, there’s nothing about FP that inherently makes the same task hard.
It just happens to be the cheapest and most reliable tech I've come across to run my businesses on.